diff --git a/.asf.yaml b/.asf.yaml new file mode 100644 index 0000000000..27b3dea710 --- /dev/null +++ b/.asf.yaml @@ -0,0 +1,51 @@ +# +# 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. +# + +github: + description: EventMesh is a dynamic event-driven application runtime used to decouple the application and backend middleware layer, which supports a wide range of use cases that encompass complex multi-cloud, widely distributed topologies using diverse technology stacks. + homepage: https://eventmesh.apache.org/ + labels: + - pubsub + - event-mesh + - event-gateway + - event-driven + - event-streaming + - event-sourcing + - event-governance + - event-routing + - cloud-native + - serverless + - serverless-workflow + - esb + - message-bus + - cqrs + - multi-runtime + - microservice + - state-management + - hacktoberfest + - hacktoberfest2022 + enabled_merge_buttons: + squash: true + merge: true + rebase: false + protected_branches: + master: + required_status_checks: + strict: true + required_pull_request_reviews: + dismiss_stale_reviews: true + required_approving_review_count: 1 diff --git a/.coveralls.yml b/.coveralls.yml deleted file mode 100644 index cf27a37024..0000000000 --- a/.coveralls.yml +++ /dev/null @@ -1 +0,0 @@ -service_name: travis-pro diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..7eefbc7944 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,106 @@ +# +# 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. +# + +name: Bug report +title: "[Bug] Bug title " +description: If something isn't working as expected. +labels: [ "bug" ] +body: + - type: markdown + attributes: + value: | + For better global communication, Please write in English. + + - type: checkboxes + attributes: + label: Search before asking + description: > + Please make sure to search in the [issues](https://github.com/apache/eventmesh/issues?q=is%3Aissue) + first to see whether the same issue was reported already. + options: + - label: > + I had searched in the [issues](https://github.com/apache/eventmesh/issues?q=is%3Aissue) and found + no similar issues. + required: true + + - type: dropdown + attributes: + label: Environment + description: Describe the environment. + options: + - Mac + - Windows + - Linux + - Other + validations: + required: true + + - type: dropdown + attributes: + label: EventMesh version + description: Describe the EventMesh version. + options: + - master + - 1.5.0 + - 1.4.0 + - 1.3.0 + - 1.2.0 + - Other + validations: + required: true + + - type: textarea + attributes: + label: What happened + description: Describe what happened. + placeholder: > + A clear and concise description of what the bug is. + validations: + required: true + + - type: textarea + attributes: + label: How to reproduce + description: > + Describe the steps to reproduce the bug here. + placeholder: > + Please make sure you provide a reproducible step-by-step case of how to reproduce the problem + as minimally and precisely as possible. + validations: + required: true + + - type: textarea + attributes: + label: Debug logs + description: Anything else we need to know? + placeholder: > + Add your debug logs here. + validations: + required: false + + - type: checkboxes + attributes: + label: Are you willing to submit PR? + description: > + This is absolutely not required, but we are happy to guide you in the contribution process + especially if you already have a good understanding of how to implement the fix. + options: + - label: Yes I am willing to submit a PR! + + - type: markdown + attributes: + value: "Thanks for completing our form!" diff --git a/.github/ISSUE_TEMPLATE/documentation_related.yml b/.github/ISSUE_TEMPLATE/documentation_related.yml new file mode 100644 index 0000000000..9841b8caf8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation_related.yml @@ -0,0 +1,60 @@ +# +# 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. +# + +name: Documentation Related +title: "[Doc] Documentation Related " +description: I find some issues related to the documentation. +labels: [ "documentation" ] +body: + - type: markdown + attributes: + value: | + For better global communication, Please write in English. + + - type: checkboxes + attributes: + label: Search before asking + description: > + Please make sure to search in the [issues](https://github.com/apache/eventmesh/issues?q=is%3Aissue) + first to see whether the same issue was reported already. + options: + - label: > + I had searched in the [issues](https://github.com/apache/eventmesh/issues?q=is%3Aissue) and found + no similar issues. + required: true + + - type: textarea + attributes: + label: Documentation Related + description: Describe the suggestion about document. + placeholder: > + e.g There is a typo + validations: + required: true + + - type: checkboxes + attributes: + label: Are you willing to submit PR? + description: > + This is absolutely not required, but we are happy to guide you in the contribution process + especially if you already have a good understanding of how to implement the fix. + options: + - label: Yes I am willing to submit a PR! + + - type: markdown + attributes: + value: "Thanks for completing our form!" \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/enhancement_request.yml b/.github/ISSUE_TEMPLATE/enhancement_request.yml new file mode 100644 index 0000000000..b4bee79aba --- /dev/null +++ b/.github/ISSUE_TEMPLATE/enhancement_request.yml @@ -0,0 +1,70 @@ +# +# 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. +# + +name: Enhancement Request +title: "[Enhancement] Enhancement title" +description: I want to suggest an enhancement for this project +labels: [ "enhancement" ] +body: + - type: markdown + attributes: + value: | + For better global communication, Please write in English. + + - type: checkboxes + attributes: + label: Search before asking + description: > + Please make sure to search in the [issues](https://github.com/apache/eventmesh/issues?q=is%3Aissue) + first to see whether the same issue was reported already. + options: + - label: > + I had searched in the [issues](https://github.com/apache/eventmesh/issues?q=is%3Aissue) and found + no similar issues. + required: true + + - type: textarea + attributes: + label: Enhancement Request + description: Describe the suggestion. + placeholder: > + First of all: Have you checked the docs https://github.com/apache/incubator-eventmesh/tree/develop/docs, + or GitHub issues whether someone else has already reported your issue? + validations: + required: true + + - type: textarea + attributes: + label: Describe the solution you'd like + description: Describe the suggestion. + placeholder: > + A clear and concise description of what you want to happen. Add any considered drawbacks. + validations: + required: true + + - type: checkboxes + attributes: + label: Are you willing to submit PR? + description: > + This is absolutely not required, but we are happy to guide you in the contribution process + especially if you already have a good understanding of how to implement the fix. + options: + - label: Yes I am willing to submit a PR! + + - type: markdown + attributes: + value: "Thanks for completing our form!" \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000000..b04ec7aff9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,62 @@ +# +# 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. +# + +name: Feature Request +title: "[Feature] Feature title " +description: I want to suggest a feature for this project. +labels: [ "feature" ] +body: + - type: markdown + attributes: + value: | + For better global communication, Please write in English. + + - type: checkboxes + attributes: + label: Search before asking + description: > + Please make sure to search in the [issues](https://github.com/apache/eventmesh/issues?q=is%3Aissue) + first to see whether the same issue was reported already. + options: + - label: > + I had searched in the [issues](https://github.com/apache/eventmesh/issues?q=is%3Aissue) and found + no similar issues. + required: true + + - type: textarea + attributes: + label: Feature Request + description: Describe the feature. + placeholder: > + First of all: Have you checked the docs https://github.com/apache/incubator-eventmesh/tree/develop/docs, + or GitHub issues whether someone else has already reported your issue? + Maybe the feature already exists? + validations: + required: true + + - type: checkboxes + attributes: + label: Are you willing to submit PR? + description: > + This is absolutely not required, but we are happy to guide you in the contribution process + especially if you already have a good understanding of how to implement the fix. + options: + - label: Yes I am willing to submit a PR! + + - type: markdown + attributes: + value: "Thanks for completing our form!" diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 0000000000..bd39533a10 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,51 @@ +# +# 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. +# + +name: Question +title: "[Question] Question title " +description: I have a question that isn't answered in docs or issue. +labels: [ "question" ] +body: + - type: markdown + attributes: + value: | + For better global communication, Please write in English. + + - type: checkboxes + attributes: + label: Search before asking + description: > + Please make sure to search in the [issues](https://github.com/apache/eventmesh/issues?q=is%3Aissue) + first to see whether the same issue was reported already. + options: + - label: > + I had searched in the [issues](https://github.com/apache/eventmesh/issues?q=is%3Aissue) and found + no similar issues. + required: true + + - type: textarea + attributes: + label: Question + description: Describe your question. + placeholder: > + Describe your question here :D + validations: + required: true + + - type: markdown + attributes: + value: "Thanks for completing our form!" diff --git a/.github/ISSUE_TEMPLATE/unit_test.yml b/.github/ISSUE_TEMPLATE/unit_test.yml new file mode 100644 index 0000000000..4dcfdafc64 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/unit_test.yml @@ -0,0 +1,86 @@ +# +# 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. +# + +name: Unit Test +title: "[Unit Test] Unit test title" +description: I want to do some unit tests for this project +labels: [ "testing" ] +body: + - type: markdown + attributes: + value: | + For better global communication, Please write in English. + + - type: checkboxes + attributes: + label: Search before asking + description: > + Please make sure to search in the [issues](https://github.com/apache/eventmesh/issues?q=is%3Aissue) + first to see whether the same issue was reported already. + options: + - label: > + I had searched in the [issues](https://github.com/apache/eventmesh/issues?q=is%3Aissue) and found + no similar issues. + required: true + + - type: checkboxes + attributes: + label: Read the unit testing guidelines + description: > + Read the [unit testing guidelines](https://github.com/apache/incubator-eventmesh/blob/master/docs/en/contribute/02-write-unit-test.md) before writing unit test code. + options: + - label: > + I have read. + required: true + + - type: textarea + attributes: + label: Unit test request + description: Describe the unit test. + placeholder: > + First of all: Have you checked the docs https://github.com/apache/incubator-eventmesh/tree/develop/docs, + or GitHub issues whether someone else has already reported your issue? + Maybe the unit tests you want to do have already been done? + validations: + required: true + + - type: textarea + attributes: + label: Describe the unit tests you want to do + description: Describe the unit test. + value: | + Module name: + Located at: + Task status: ×(unfinished) / √(finished) + | Task Status | Class | Type | + | :------: | :------ | :------ | + | × | xxxxxx | xxxxxx | + validations: + required: true + + - type: checkboxes + attributes: + label: Are you willing to submit PR? + description: > + This is absolutely not required, but we are happy to guide you in the contribution process + especially if you already have a good understanding of how to implement the fix. + options: + - label: Yes I am willing to submit a PR! + + - type: markdown + attributes: + value: "Thanks for completing our form!" \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..1bc7ac8d31 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,46 @@ + + + + +Fixes #. + +### Motivation + +*Explain the content here.* +*Explain why you want to make the changes and what problem you're trying to solve.* + + + +### Modifications + +*Describe the modifications you've done.* + + + +### Documentation + +- Does this pull request introduce a new feature? (yes / no) +- If yes, how is the feature documented? (not applicable / docs / JavaDocs / not documented) +- If a feature is not applicable for documentation, explain why? +- If a feature is not documented yet in this PR, please create a followup issue for adding the documentation diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..04f8e32117 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,84 @@ +# +# 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. +# + +name: "Continuous Integration" + +on: + push: + branches: ['*'] + pull_request: + branches: [ '*' ] + +jobs: + build: + name: Build + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macOS-latest] + java: [8, 11] + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + # 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. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + languages: ${{ matrix.language }} + + - name: Set up JDK ${{ matrix.java }} + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: ${{ matrix.java }} + + - name: Build + run: ./gradlew clean build jar dist jacocoTestReport + + - name: Install plugin + run: ./gradlew installPlugin + + - name: Perform CodeQL analysis + uses: github/codeql-action/analyze@v1 + + - name: Upload coverage report to codecov.io + run: bash <(curl -s https://codecov.io/bash) || echo 'Failed to upload coverage report!' + + license-check: + name: License Check + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Check license header + uses: apache/skywalking-eyes@main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check third party dependencies + run: | + ./gradlew clean jar dist -x test -x checkstyleMain -x javaDoc && ./gradlew installPlugin && ./gradlew tar && sh tools/dependency-check/check-dependencies.sh && echo "Thirty party dependencies check success" diff --git a/.github/workflows/eventmesh-server-go.yml b/.github/workflows/eventmesh-server-go.yml new file mode 100644 index 0000000000..2d3ed9a542 --- /dev/null +++ b/.github/workflows/eventmesh-server-go.yml @@ -0,0 +1,52 @@ +# +# 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. +# + +name: "Continuous Integration of EventMesh Server Go" + +on: + push: + branches: ['*'] + pull_request: + branches: ['*'] + +jobs: + build: + name: Build + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - uses: actions/setup-go@v3 + with: + go-version-file: 'eventmesh-server-go/go.mod' + - run: go version + + - name: Download components + run: go mod tidy + working-directory: eventmesh-server-go + + - name: Build application + run: make build + working-directory: eventmesh-server-go + + - name: Test application + run: make test + working-directory: eventmesh-server-go \ No newline at end of file diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml new file mode 100644 index 0000000000..7ce1a31e46 --- /dev/null +++ b/.github/workflows/greetings.yml @@ -0,0 +1,72 @@ +# +# 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. +# + +name: Greetings + +on: [pull_request_target, issues] + +jobs: + greeting: + name: Greeting + runs-on: ubuntu-latest + steps: + - uses: actions/first-interaction@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + issue-message: | + Welcome to the Apache EventMesh (incubating) community!! + We are glad that you are contributing by opening this issue. :D + + Please make sure to include all the relevant context. + We will be here shortly. + + If you are interested in contributing to our project, please let us know! + You can check out our contributing guide on [contributing to EventMesh](https://github.com/apache/incubator-eventmesh/blob/develop/CONTRIBUTING.md). + + Want to get closer to the community? + + WeChat Group: + ![wechat_qr](https://github.com/apache/incubator-eventmesh/blob/master/docs/images/contact/wechat-assistant.jpg?raw=true) + + Mailing Lists: + | Name | Description |Subscribe |Unsubscribe|Archive + | ---- | ---- |---- | ---- | ---- | + |Users |User support and questions mailing list| [Subscribe](mailto:users-subscribe@eventmesh.incubator.apache.org) |[Unsubscribe](mailto:users-unsubscribe@eventmesh.incubator.apache.org) |[Mail Archives](https://lists.apache.org/list.html?users@eventmesh.apache.org)| + |Development |Development related discussions| [Subscribe](mailto:dev-subscribe@eventmesh.incubator.apache.org) |[Unsubscribe](mailto:dev-unsubscribe@eventmesh.incubator.apache.org) |[Mail Archives](https://lists.apache.org/list.html?dev@eventmesh.apache.org)| + |Commits |All commits to repositories| [Subscribe](mailto:commits-subscribe@eventmesh.incubator.apache.org) |[Unsubscribe](mailto:commits-unsubscribe@eventmesh.incubator.apache.org) |[Mail Archives](https://lists.apache.org/list.html?commits@eventmesh.apache.org)| + + pr-message: | + Welcome to the Apache EventMesh (incubating) community!! + This is your first PR in our project. We're very excited to have you onboard contributing. Your contributions are greatly appreciated! + + Please make sure that the changes are covered by tests. + We will be here shortly. + Let us know if you need any help! + + Want to get closer to the community? + + WeChat Group: + ![wechat_qr](https://github.com/apache/incubator-eventmesh/blob/master/docs/images/contact/wechat-assistant.jpg?raw=true) + + Mailing Lists: + | Name | Description |Subscribe |Unsubscribe|Archive + | ---- | ---- |---- | ---- | ---- | + |Users |User support and questions mailing list| [Subscribe](mailto:users-subscribe@eventmesh.incubator.apache.org) |[Unsubscribe](mailto:users-unsubscribe@eventmesh.incubator.apache.org) |[Mail Archives](https://lists.apache.org/list.html?users@eventmesh.apache.org)| + |Development |Development related discussions| [Subscribe](mailto:dev-subscribe@eventmesh.incubator.apache.org) |[Unsubscribe](mailto:dev-unsubscribe@eventmesh.incubator.apache.org) |[Mail Archives](https://lists.apache.org/list.html?dev@eventmesh.apache.org)| + |Commits |All commits to repositories| [Subscribe](mailto:commits-subscribe@eventmesh.incubator.apache.org) |[Unsubscribe](mailto:commits-unsubscribe@eventmesh.incubator.apache.org) |[Mail Archives](https://lists.apache.org/list.html?commits@eventmesh.apache.org)| diff --git a/.gitignore b/.gitignore index 936bb5cb18..244764cf97 100644 --- a/.gitignore +++ b/.gitignore @@ -9,11 +9,24 @@ logs *.iws *.class *.log +*.log.* .idea build .classpath .project test-output dist +out .pmd classes +package-lock.json +node_modules +.run +*.log + +h2/db.mv.db + +# license check tmp file +all-dependencies.txt +self-modules.txt +third-party-dependencies.txt diff --git a/.licenserc.yaml b/.licenserc.yaml new file mode 100644 index 0000000000..92aff62557 --- /dev/null +++ b/.licenserc.yaml @@ -0,0 +1,46 @@ +# +# 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. +# + +header: + license: + spdx-id: Apache-2.0 + copyright-owner: Apache Software Foundation + + paths-ignore: + - '.github/PULL_REQUEST_TEMPLATE' + - '.gitmodules' + - '**/.gitkeep' + - '**/.gitignore' + - '**/*.md' + - '**/*.json' + - '**/*.ftl' + - '**/*.iml' + - '**/*.ini' + - '**/*.crt' + - '**/*.pem' + - '**/go.sum' + - '**/Cargo.lock' + - 'LICENSE' + - 'NOTICE' + - 'DISCLAIMER-WIP' + - 'gradlew' + - 'gradlew.bat' + - '**/*.txt' + + comment: on-failure diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 4c2ba8ba57..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -dist: trusty - -language: java -jdk: -- oraclejdk8 - -script: -- travis_retry gradle check - -after_success: -- gradle clean test jacocoAllTestReport coveralls - -env: - global: - - secure: "T1QAuaAzcB7K8YjAAVVb4P9+W0JAdOFbyBwRxliyyoSZUShlIqa0eE7ioXHXWBP/d5f3XtROse6lq2qILqcU9sFSncKE2vRJlwJ5p7R23WIsCXdV70A9AVE2gLJcIJiOTMwd/YYYzNDrGLp3CSJNcKo8t7t70V2j/11I9xPTOHnaZ8FHGC3d/7bjfR/+g/3d4EOCvV8Vm6ndEmmailmF8OJ/kcbuRbArKIehjUwNDyQZfwAc9+vvPZlHgnQvR1pJ/KiK6muEIi7RQohDq7lMTmcc2LZSYgy/+aqFrmBcQwXScABFmSwysQ4KMXfrCqqMsBdmvno/NoKVGofHHKdym/oauv/G3lxLx5sgM9A7ZSFBK08x08r7u/6TDsTFmQ9LzVFDNo/OLZhxs3dr9x2C9Pa2A7IP1i1oVbbYkwBJv4z6o3khWpQAAY/IWijlCZ9vkjFfqdIXbvlPqamEaFRAmK5I3MVqL2+eBF+2Or/zwv4rXjo+v5LUKTfmDl77QUshPv6J+hblbBR0cJ/ZTSh9rHgdqhEzPGSt3e0YrEefkKWfinBr8TjIsHgQgmfU8Kz7gf7tvioOuAgKj4WlgEQJs3dPp7J5zxFVNMM6teAMFy8c2MtAdzKrs13Ri1qZWtL6B7JWlH6yhHqhKghyJhRjUFNVZnBkA/z9gzDKZ+tz2m8=" \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index c03c59a0bc..0000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,68 +0,0 @@ -# Contributing to EventMesh - -Welcome to EventMesh! This document is a guideline about how to contribute to EventMesh. -If you find something incorrect or missing, please leave comments / suggestions. - -## Before you get started - -### Setting up your development environment - -You should have JDK installed in your operating system. - -## Contributing - -We are always very happy to have contributions, whether for typo fix, bug fix or big new features. -Please do not ever hesitate to ask a question or send a pull request. - -We strongly value documentation and integration with other projects. -We are very glad to accept improvements for these aspects. - -### GitHub workflow - -We use the `develop` branch as the development branch, which indicates that this is an unstable branch. - -Here are the workflow for contributors: - -1. Fork to your own -2. Clone fork to local repository -3. Create a new branch and work on it -4. Keep your branch in sync -5. Commit your changes (make sure your commit message concise) -6. Push your commits to your forked repository -7. Create a pull request - -Please follow [the pull request template](./.github/PULL_REQUEST_TEMPLATE.md). -Please make sure the PR has a corresponding issue. - -After creating a PR, one or more reviewers will be assigned to the pull request. -The reviewers will review the code. - -Before merging a PR, squash any fix review feedback, typo, merged, and rebased sorts of commits. -The final commit message should be clear and concise. - -### Open an issue / PR - -We use [GitHub Issues](https://github.com/WeBankFinTech/EventMesh/issues) and [Pull Requests](https://github.com/WeBankFinTech/EventMesh/pulls) for trackers. - -If you find a typo in a document, find a bug in code, or want new features, or want to give suggestions, -you can [open an issue on GitHub](https://github.com/WeBankFinTech/EventMesh/issues/new) to report it. -Please follow the guideline message in the issue template. - -If you want to contribute, please follow the [contribution workflow](#github-workflow) and create a new pull request. -If your PR contains large changes, e.g. component refactor or new components, please write detailed documents -about its design and usage. - -Note that a single pull request should not be too large. If heavy changes are required, it's better to separate the changes -to a few individual PRs. - -### Code review - -All code should be well reviewed by one or more committers. Some principles: - -- Readability: Important code should be well-documented. Comply with our code style. -- Elegance: New functions, classes or components should be well-designed. -- Testability: Important code should be well-tested (high unit test coverage). - -## Community - -### Contact us diff --git a/DISCLAIMER-WIP b/DISCLAIMER-WIP new file mode 100644 index 0000000000..e72dd1b9d0 --- /dev/null +++ b/DISCLAIMER-WIP @@ -0,0 +1,19 @@ +Apache EventMesh is an effort undergoing incubation at The Apache Software Foundation (ASF), +sponsored by the Apache Incubator PMC. + +Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, +communications, and decision-making process have stabilized in a manner consistent with other successful ASF projects. + +While incubation status is not necessarily a reflection of the completeness or stability of the code, +it does indicate that the project has yet to be fully endorsed by the ASF. + +Some of the incubating project’s releases may not be fully compliant with ASF policy. +For example, releases may have incomplete or un-reviewed licensing conditions. +What follows is a list of issues the project is currently aware of (this list is likely to be incomplete): + +1- Releases may have incomplete licensing conditions + + +If you are planning to incorporate this work into your product/project, +please be aware that you will need to conduct a thorough licensing review to determine the overall implications of including this work. +For the current status of this project through the Apache Incubator, visit: https://incubator.apache.org/projects/eventmesh.html diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000000..76091d57bb --- /dev/null +++ b/NOTICE @@ -0,0 +1,5 @@ +Apache EventMesh (incubating) +Copyright 2021-2022 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/README.md b/README.md index 1d59312312..1e7a395aa7 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,108 @@ -[![Build Status](https://www.travis-ci.org/WeBankFinTech/DeFiBus.svg?branch=master)](https://www.travis-ci.org/WeBankFinTech/EventMesh) [![Coverage Status](https://coveralls.io/repos/github/WeBankFinTech/DeFiBus/badge.svg?branch=master)](https://coveralls.io/github/WeBankFinTech/EventMesh?branch=master) +
-## What is an Event Mesh? -This diagram shows where an event mesh fits in an application stack relative to other technologies such as service mesh: -![architecture1](docs/images/eventmesh-define.png) +

+ +
-An event mesh is a configurable and dynamic infrastructure layer for distributing events among decoupled applications, cloud services and devices. It enables event communications to be governed, flexible, reliable and fast. An event mesh is created and enabled through a network of interconnected event meshers. +[![CI status](https://img.shields.io/github/workflow/status/apache/incubator-eventmesh/Continuous%20Integration?logo=github&style=for-the-badge)](https://github.com/apache/incubator-eventmesh/actions/workflows/ci.yml) +[![CodeCov](https://img.shields.io/codecov/c/gh/apache/incubator-eventmesh/master?logo=codecov&style=for-the-badge)](https://codecov.io/gh/apache/incubator-eventmesh) +[![Code Quality: Java](https://img.shields.io/lgtm/grade/java/g/apache/incubator-eventmesh.svg?logo=lgtm&logoWidth=18&style=for-the-badge)](https://lgtm.com/projects/g/apache/incubator-eventmesh/context:java) +[![Total Alerts](https://img.shields.io/lgtm/alerts/g/apache/incubator-eventmesh.svg?logo=lgtm&logoWidth=18&style=for-the-badge)](https://lgtm.com/projects/g/apache/incubator-eventmesh/alerts/) -## What are the core capabilities of an event mesh? -This diagram shows the architecture of EventMesh: -![architecture2](docs/images/eventmesh-arch.png) +[![License](https://img.shields.io/github/license/apache/incubator-eventmesh?style=for-the-badge)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![GitHub Release](https://img.shields.io/github/v/release/apache/eventmesh?style=for-the-badge)](https://github.com/apache/incubator-eventmesh/releases) +[![Slack Status](https://img.shields.io/badge/slack-join_chat-blue.svg?logo=slack&style=for-the-badge)](https://join.slack.com/t/apacheeventmesh/shared_invite/zt-1hgto0wcm-KXKz8pJGUwrWdk00juaQSw) -An event mesh allows events from one application to be dynamically routed and received by any other application no matter where these applications are deployed (no cloud, private cloud, public cloud). -The generic capabilities of an event mesh: -* inherently ‘event-driven;’ -* created by connecting event meshers; -* environment agnostic (can be deployed anywhere); and, -* dynamic. +[📦 Documentation](https://eventmesh.apache.org/docs/introduction) | +[📔 Examples](https://github.com/apache/incubator-eventmesh/tree/master/eventmesh-examples) | +[⚙️ Roadmap](https://github.com/apache/incubator-eventmesh/blob/master/docs/en/roadmap.md) | +[🌐 简体中文](README.zh-CN.md) +
-Key components: -* eventmesh-emesher : an middleware to transmit events between event producers and consumers, support cloud native apps and microservices -* eventmesh-sdk-java : support for popular open standard protocols and APIs, including REST/HTTP, AMQP, MQTT, Websocket and JMS, gRPC etc. -* eventmesh-registry : automatically routes events between applications and services connected to seperate event meshers -* eventmesh-governance : governace layer for event producers and consumers -* eventmesh-acl : security at various level of authentication, authorization and topic/channel access control -* eventmesh-store : the store layer of Event-Mesh which implemented with [DeFiBus](https://github.com/WeBankFinTech/DeFiBus)(based on RocketMQ in financial scenario) or RocketMQ by default. We wish the store layeris a general solution and can use any store implement such as kafka, redis ,blockchain etc. -## Quick Start -Coming soon... +# Apache EventMesh (Incubating) + +**Apache EventMesh (Incubating)** is a dynamic [event-driven](https://en.wikipedia.org/wiki/Event-driven_architecture) application multi-runtime used to decouple the application and backend middleware layer, which supports a wide range of use cases that encompass complex multi-cloud, widely distributed topologies using diverse technology stacks. + +### EventMesh Architecture + +![EventMesh Architecture](docs/images/eventmesh-architecture-2.png) + +## Features + +Apache EventMesh (Incubating) has a vast amount of features to help users achieve their goals. Let us share with you some of the key features EventMesh has to offer: + +- Built around the [CloudEvents](https://cloudevents.io) specification. +- Rapidty extendsible language sdk around [gRPC](https://grpc.io) protocols. +- Rapidty extendsible middleware by connectors such as [Apache RocketMQ](https://rocketmq.apache.org), [Apache Kafka](https://kafka.apache.org), [Apache Pulsar](https://pulsar.apache.org), [RabbitMQ](https://rabbitmq.com), [Redis](https://redis.io), [Pravega](https://cncf.pravega.io), and [RDMS](https://en.wikipedia.org/wiki/Relational_database)(in progress) using [JDBC](https://en.wikipedia.org/wiki/Java_Database_Connectivity). +- Rapidty extendsible controller such as [Consul](https://consulproject.org/en/), [Nacos](https://nacos.io), [ETCD](https://etcd.io) and [Zookeeper](https://zookeeper.apache.org/). +- Guaranteed at-least-once delivery. +- Deliver events between multiple EventMesh deployments. +- Event schema management by catalog service. +- Powerful event orchestration by [Serverless workflow](https://serverlessworkflow.io/) engine. +- Powerful event filtering and transformation. +- Rapid, seamless scalability to add new machines. + +## Roadmap + +Please go to the [roadmap](https://github.com/apache/incubator-eventmesh/blob/master/docs/en/roadmap.md) to get the release history and new features of Apache EventMesh (Incubating). + +## Quick start +Here are the guidelines: + +[Step 1: Deploy eventmesh-store](docs/en/instruction/01-store.md) + +[Step 2: Start eventmesh-runtime](docs/en/instruction/02-runtime.md) + +[Step 3: Run our demos](docs/en/instruction/03-demo.md) + +Besides, we also provide the docker-version guidelines for you if you prefer Docker: + +[Step 1: Deploy eventmesh-store using docker](docs/en/instruction/01-store-with-docker.md) + +[Step 2: Start eventmesh-runtime using docker](docs/en/instruction/02-runtime-with-docker.md) + +[Step 3: Run our demos](docs/en/instruction/03-demo.md) ## Contributing -Contributions are always welcomed! Please see [CONTRIBUTING](CONTRIBUTING.md) for detailed guidelines. -You can start with the issues labeled with good first issue. +Each contributor has played an important role in promoting the robust development of Apache EventMesh (Incubating). We sincerely appreciate all contributors who have contributed code and documents. + +- [Contributing Guideline](https://github.com/apache/incubator-eventmesh/blob/master/docs/en/contribute/03-new-contributor-guidelines.md) +- [Good First Issues](https://github.com/apache/incubator-eventmesh/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) + +Here is the [List of Contributors](https://github.com/apache/incubator-eventmesh/graphs/contributors), thank you all! :) + + + + + + +## CNCF Landscape + +
+ + + + +Apache EventMesh (Incubating) enriches the CNCF Cloud Native Landscape. + +
## License -[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) Copyright (C) Apache Software Foundation -## Contacts +Apache EventMesh (Incubating) is licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). + +## Community +|WeChat Assistant|WeChat Public Account|Slack| +|-|-|-| +|||[Join Slack Chat](https://join.slack.com/t/apacheeventmesh/shared_invite/zt-1hgto0wcm-KXKz8pJGUwrWdk00juaQSw)| +### Mailing List +|Name|Description|Subscribe|Unsubscribe|Archive +|-|-|-|-|-| +|Users|User discussion|[Subscribe](mailto:users-subscribe@eventmesh.incubator.apache.org)|[Unsubscribe](mailto:users-unsubscribe@eventmesh.incubator.apache.org)|[Mail Archives](https://lists.apache.org/list.html?users@eventmesh.apache.org)| +|Development|Development discussion (Design Documents, Issues, etc.)|[Subscribe](mailto:dev-subscribe@eventmesh.incubator.apache.org)|[Unsubscribe](mailto:dev-unsubscribe@eventmesh.incubator.apache.org)|[Mail Archives](https://lists.apache.org/list.html?dev@eventmesh.apache.org)| +|Commits|Commits to related repositories| [Subscribe](mailto:commits-subscribe@eventmesh.incubator.apache.org) |[Unsubscribe](mailto:commits-unsubscribe@eventmesh.incubator.apache.org) |[Mail Archives](https://lists.apache.org/list.html?commits@eventmesh.apache.org)| diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 0000000000..8477f1816d --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,118 @@ +
+ +

+ +
+ +[![CI status](https://img.shields.io/github/workflow/status/apache/incubator-eventmesh/Continuous%20Integration?logo=github&style=for-the-badge)](https://github.com/apache/incubator-eventmesh/actions/workflows/ci.yml) +[![CodeCov](https://img.shields.io/codecov/c/gh/apache/incubator-eventmesh/master?logo=codecov&style=for-the-badge)](https://codecov.io/gh/apache/incubator-eventmesh) +[![Code Quality: Java](https://img.shields.io/lgtm/grade/java/g/apache/incubator-eventmesh.svg?logo=lgtm&logoWidth=18&style=for-the-badge)](https://lgtm.com/projects/g/apache/incubator-eventmesh/context:java) +[![Total Alerts](https://img.shields.io/lgtm/alerts/g/apache/incubator-eventmesh.svg?logo=lgtm&logoWidth=18&style=for-the-badge)](https://lgtm.com/projects/g/apache/incubator-eventmesh/alerts/) + +[![License](https://img.shields.io/github/license/apache/incubator-eventmesh?style=for-the-badge)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![GitHub Release](https://img.shields.io/github/v/release/apache/eventmesh?style=for-the-badge)](https://github.com/apache/incubator-eventmesh/releases) +[![Slack Status](https://img.shields.io/badge/slack-join_chat-blue.svg?logo=slack&style=for-the-badge)](https://join.slack.com/t/apacheeventmesh/shared_invite/zt-16y1n77va-q~JepYy3RqpkygDYmQaQbw) + +[📦 文档 (英文)](https://eventmesh.apache.org/docs/introduction) | +[📔 例子](https://github.com/apache/incubator-eventmesh/tree/master/eventmesh-examples) | +[⚙️ 路线图](https://eventmesh.apache.org/docs/roadmap) | +[🌐 英文版](README.md) +
+ +# Apache EventMesh (Incubating) + +**Apache EventMesh (Incubating)** 是一个用于解耦应用和后端中间件层的的动态云原生 [事件驱动](https://en.wikipedia.org/wiki/Event-driven_architecture) 架构基础设施。它支持广泛的用例,包括复杂的混合云、使用了不同技术栈的分布式架构。 + +## 特性 + +### 多运行时微服务架构 + +![EventMesh Architecture](docs/images/eventmesh-architecture.png) + +### 编排 + +![EventMesh Orchestration](docs/images/eventmesh-orchestration.png) + +### 数据网格 + +![EventMesh Data Mesh](docs/images/eventmesh-bridge.png) + +## 组件 + +**Apache EventMesh (Incubating)** 由多个组件组成,这些组件集成了不同的中间件和消息传输协议,以增强应用程序运行时的功能。 + +- **eventmesh-runtime**: 在生产者和消费者之间传输事件的中间件,它支持云原生应用程序和微服务。 +- **eventmesh-sdk-java**: 支持 HTTP、TCP 和 [gRPC](https://grpc.io) 协议的 Java SDK。 +- **eventmesh-sdk-go**: 支持 HTTP、TCP 和 [gRPC](https://grpc.io) 协议的 Golang SDK。 +- **eventmesh-connector-plugin**: 连接 [Apache RocketMQ](https://rocketmq.apache.org)、 [Apache Kafka](https://kafka.apache.org)、[Apache Pulsar](https://pulsar.apache.org/) 和 [Redis](https://redis.io) 等中间件的插件集合。 +- **eventmesh-registry-plugin**: 集成服务注册表的插件集合,如 [Nacos](https://nacos.io) 和 [etcd](https://etcd.io)。 + +- **eventmesh-security-plugin**: 实现安全机制的插件的集合,如 ACL(访问控制列表)、认证和授权。 + +- **eventmesh-protocol-plugin**: 实现消息传递协议的插件集合,如 [CloudEvents](https://cloudevents.io) 和 [MQTT](https://mqtt.org)。 + +- **eventmesh-admin**: 客户端管理、主题管理、订阅管理和其他管理。 + +## 下载 + +你可以在这个页面 [release page](https://eventmesh.apache.org/download) 获取所有的历史发布版本。 + +## 快速开始指引 + +[Step 1: Deploy eventmesh-store](docs/zh/instruction/01-store.md) + +[Step 2: Start eventmesh-runtime](docs/zh/instruction/02-runtime.md) + +[Step 3: Run our demos](docs/zh/instruction/03-demo.md) + +除此之外,我们还提供了 Docker 版本的快速开始指引,方便您借助 Docker 来初探我们的项目: + +[Step 1: Deploy eventmesh-store using docker](docs/zh/instruction/01-store-with-docker.md) + +[Step 2: Start eventmesh-runtime using docker](docs/zh/instruction/02-runtime-with-docker.md) + +[Step 3: Run our demos](docs/zh/instruction/03-demo.md) + + + +## 贡献这个项目 + +每一名贡献者都在这个项目的发展上都是至关重要的。我们真诚地感谢所有对代码和文档的贡献者!想要尝试贡献的可以看看以下三个链接。 + +- [贡献准则](https://eventmesh.apache.org/docs/contribute/contribute) +- [值得新人尝试的 Issue](https://github.com/apache/incubator-eventmesh/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) + +这是项目的[贡献者名单](https://github.com/apache/incubator-eventmesh/graphs/contributors) +,感谢各位的大力支持 :) + + + + + +## CNCF Landscape + +
+ + + + +Apache EventMesh (Incubating) enriches the CNCF Cloud Native Landscape. +
+ +## 开源授权 + +Apache EventMesh (Incubating) is licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). + +## 社区 + +|微信小助手|微信公众号|Slack| +|-|-|-| +|||[加入 Slack](https://join.slack.com/t/apacheeventmesh/shared_invite/zt-16y1n77va-q~JepYy3RqpkygDYmQaQbw)| + +### 邮件名单 + +| 列表名称 | 描述 |订阅 |取消订阅|邮件列表存档 +| ---- | ---- |---- | ---- | ---- | +|用户 |用户支持与用户问题| [点击订阅](mailto:users-subscribe@eventmesh.incubator.apache.org) |[点击取消订阅](mailto:users-unsubscribe@eventmesh.incubator.apache.org) |[邮件列表存档](https://lists.apache.org/list.html?users@eventmesh.apache.org)| +|开发 |开发相关| [点击订阅](mailto:dev-subscribe@eventmesh.incubator.apache.org) |[点击取消订阅](mailto:dev-unsubscribe@eventmesh.incubator.apache.org) |[邮件列表存档](https://lists.apache.org/list.html?dev@eventmesh.apache.org)| +|Commits |所有与仓库相关的 commits 信息通知| [点击订阅](mailto:commits-subscribe@eventmesh.incubator.apache.org) |[点击取消订阅](mailto:commits-unsubscribe@eventmesh.incubator.apache.org) |[邮件列表存档](https://lists.apache.org/list.html?commits@eventmesh.apache.org)| diff --git a/build.gradle b/build.gradle index e69de29bb2..6b1f72839b 100644 --- a/build.gradle +++ b/build.gradle @@ -0,0 +1,517 @@ +/* + * 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. + */ + +import java.util.concurrent.TimeUnit + +buildscript { + repositories { + maven { + url "https://maven.aliyun.com/repository/public" + } + + maven { + url "https://plugins.gradle.org/m2/" + } + } + + dependencies { + classpath "com.github.spotbugs.snom:spotbugs-gradle-plugin:5.0.3" + classpath "io.spring.gradle:dependency-management-plugin:1.0.11.RELEASE" + classpath "com.github.jk1:gradle-license-report:1.17" + } +} + +//Remove doclint warnings that pollute javadoc logs when building with java8 +if(JavaVersion.current().isJava8()){ + allprojects { + tasks.withType(Javadoc){ + options.addStringOption('xdoclint:none','-quiet') + } + } +} + +allprojects { + apply plugin: 'java' + apply plugin: "eclipse" + apply plugin: "idea" + apply plugin: "project-reports" + apply plugin: "maven-publish" + apply plugin: "com.github.spotbugs" + apply plugin: "project-reports" + apply plugin: "jacoco" + apply plugin: "pmd" + apply plugin: "java-library" + apply plugin: 'signing' + apply plugin: 'checkstyle' + + [compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8' + + compileJava.options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" + + java { + sourceCompatibility = "1.8" + targetCompatibility = "1.8" + } + + clean.doFirst { + delete 'build' + delete 'dist' + delete 'out' + } + + checkstyle { + toolVersion = '9.0' + ignoreFailures = false + showViolations = true + maxWarnings = 0 + configFile = new File("${rootDir}/style/checkStyle.xml") + } + + checkstyleMain.exclude '**/org/apache/eventmesh/client/grpc/protos**' + + dependencies { + repositories { + maven { + url "https://maven.aliyun.com/repository/public" + } + } + testImplementation "junit:junit:4.13.2" + } +} + +task tar(type: Tar) { + archiveBaseName.set(project.name) + archiveVersion.set(project.version.toString()) + archiveExtension.set('tar.gz') + compression = Compression.GZIP + destinationDirectory = new File(projectDir, 'build') + into('/') { + from 'dist' + } +} + +task zip(type: Zip) { + archiveBaseName.set(project.name) + archiveVersion.set(project.version.toString()) + archiveExtension.set('zip') + destinationDirectory = new File(projectDir, 'build') + into('/') { + from 'dist' + } +} + +task installPlugin() { + if (!new File("${rootDir}/dist").exists()) { + return + } + String[] libJars = java.util.Optional.ofNullable(new File("${rootDir}/dist/lib").list()).orElseGet(() -> new String[0]) + getAllprojects().forEach(subProject -> { + var file = new File("${subProject.projectDir}/gradle.properties") + if (!file.exists()) { + return + } + var properties = new Properties() + properties.load(new FileInputStream(file)) + var pluginType = properties.getProperty("pluginType") + var pluginName = properties.getProperty("pluginName") + if (pluginType == null || pluginName == null) { + return + } + var pluginFile = new File("${rootDir}/dist/plugin/${pluginType}/${pluginName}") + if (pluginFile.exists()) { + return + } + pluginFile.mkdirs() + println String.format( + "install plugin, pluginType: %s, pluginInstanceName: %s, module: %s", pluginType, pluginName, subProject.getName() + ) + + copy { + into "${rootDir}/dist/plugin/${pluginType}/${pluginName}" + from "${subProject.getProjectDir()}/dist/apps" + } + copy { + into "${rootDir}/dist/plugin/${pluginType}/${pluginName}" + from "${subProject.getProjectDir()}/dist/lib/" + exclude(libJars) + } + copy { + into "${rootDir}/dist/conf" + from "${subProject.getProjectDir()}/dist/conf" + exclude 'META-INF' + } + }) +} + +task printProjects() { + getAllprojects().forEach(subProject -> { + if ("EventMesh".equals(subProject.getName())) { + return + } + println String.format("%s-%s.jar", subProject.getName(), subProject.getVersion()) + }) +} + +subprojects { + + apply plugin: "io.spring.dependency-management" + + sourceSets { + main { + java.srcDirs = ['src/main/java'] + } + + test { + java.srcDirs = ['src/test/java'] + } + } + + clean.doFirst { + delete 'build' + delete 'dist' + } + + jacoco { + toolVersion = "0.8.6" + } + + jacocoTestReport { + reports { + xml.enabled true + csv.enabled false + html.enabled false + } + } + + spotbugs { + ignoreFailures = true + showProgress = true + showStackTraces = true + effort = 'default' + reportsDir = file("$buildDir/reports/spotbugs") + projectName = rootProject.name + release = version + extraArgs = ['-nested:false'] + maxHeapSize = '256m' + + } + + spotbugsMain { + + reports { + xml.enabled = false + html { + enabled = true + destination = file("$buildDir/reports/spotbugs/main/spotbugs.html") + stylesheet = 'fancy-hist.xsl' + } + } + } + + spotbugsTest { + reports { + xml.enabled = false + html { + enabled = true + destination = file("$buildDir/reports/spotbugs/test/spotbugs.html") + stylesheet = 'fancy-hist.xsl' + } + } + } + + pmd { + consoleOutput = true + toolVersion = "6.23.0" + rulesMinimumPriority = 5 + ruleSets = ["category/java/errorprone.xml", "category/java/bestpractices.xml"] + ignoreFailures = true + } + + jar { + manifest { + attributes("Specification-Version": project.version, + "Specification-Vendor": "Apache", + "Specification-Title": project.name, + "Implementation-Version": project.version, + "Implementation-Vendor": "Apache", + "Implementation-Title": project.name, + "Build-Jdk": project.findProperty("jdk") + ) + } + } + + task dist(dependsOn: ['jar']) { + doFirst { + new File("${projectDir}/dist/bin").mkdirs() + new File("${projectDir}/dist/apps").mkdirs() + new File("${projectDir}/dist/conf").mkdirs() + new File("${projectDir}/dist/lib").mkdirs() + new File("${projectDir}/dist/licenses").mkdirs() + } + Set rootProject = ["eventmesh-admin", + "eventmesh-admin-rocketmq", + "eventmesh-common", + "eventmesh-connector-api", + "eventmesh-metrics-api", + "eventmesh-registry-api", + "eventmesh-trace-api", + "eventmesh-runtime", + "eventmesh-security-api", + "eventmesh-protocol-api", + "eventmesh-starter", + "eventmesh-spi", + "eventmesh-webhook-api", + "eventmesh-webhook-admin", + "eventmesh-webhook-receive" + ] + doLast { + copy { + into("${projectDir}/dist/apps") + from project.jar.getArchivePath() + } + copy { + into("${projectDir}/dist/lib") + from project.configurations.runtimeClasspath + } + copy { + into("${projectDir}/dist/bin") + from 'bin' + } + copy { + into("${projectDir}/dist/conf") + from 'conf', sourceSets.main.resources.srcDirs + setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE) + exclude 'META-INF' + } + if (rootProject.contains(project.name)) { + new File("${rootDir}/dist/apps").mkdirs() + new File("${rootDir}/dist/lib").mkdirs() + new File("${rootDir}/dist/bin").mkdirs() + new File("${rootDir}/dist/conf").mkdirs() + copy { + into("${rootDir}/dist/apps") + from "${projectDir}/dist/apps" + } + copy { + into "${rootDir}/dist/lib" + from "${projectDir}/dist/lib" + exclude "eventmesh-*" + } + copy { + into "${rootDir}/dist/bin" + from "${projectDir}/dist/bin" + } + copy { + into "${rootDir}/dist/conf" + from "${projectDir}/dist/conf" + } + } + copy { + into "${rootDir}/dist" + from "${rootDir}/tools/third-party-licenses" + } + } + } + + javadoc { + source = sourceSets.main.java + destinationDir = reporting.file("javadoc") + } + + task packageJavadoc(type: Jar, dependsOn: ['javadoc']) { + from project.javadoc.destinationDir + classifier = 'javadoc' + } + + task packageSources(type: Jar) { + from project.sourceSets.main.allSource + classifier = 'sources' // either here or in artifacts block + } + + artifacts { + archives jar + archives packageJavadoc + archives packageSources + } + + if (!Boolean.valueOf(signEnabled)) { + tasks.whenTaskAdded { task -> + if (task.name.contains("sign")) { + task.enabled = false + } + } + } + + repositories { + maven { url "https://maven.aliyun.com/repository/public" } + mavenCentral() + mavenLocal() + } + + configurations.all { + resolutionStrategy.cacheChangingModulesFor 0, TimeUnit.SECONDS + resolutionStrategy.cacheDynamicVersionsFor 0, TimeUnit.SECONDS + } + + publishing { + publications { + mavenJava(MavenPublication) { + from components.java + artifact packageSources + artifact packageJavadoc + versionMapping { + usage('java-api') { + fromResolutionOf('runtimeClasspath') + } + usage('java-runtime') { + fromResolutionResult() + } + } + pom { + name = 'EventMesh' + description = 'Apache EventMesh' + url = 'https://github.com/apache/incubator-eventmesh' + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + developers { + developer { + id = 'Apache EventMesh(incubating)' + name = 'Apache EventMesh(incubating) of ASF' + url = 'https://eventmesh.apache.org/' + } + } + scm { + connection = 'scm:git:git@github.com:apache/incubator-eventmesh.git' + developerConnection = 'scm:git:git@github.com:apache/incubator-eventmesh.git' + url = 'https://github.com/apache/incubator-eventmesh' + } + } + } + } + repositories { + maven { + def releasesRepoUrl = 'https://repository.apache.org/service/local/staging/deploy/maven2' + def snapshotsRepoUrl = 'https://repository.apache.org/content/repositories/snapshots/' + url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl + credentials { + username apacheUserName + password apachePassWord + } + + } + } + } + + signing { + sign publishing.publications.mavenJava + } + + def grpcVersion = '1.43.2' + + dependencyManagement { + dependencies { + dependency "org.apache.commons:commons-lang3:3.6" + dependency "org.apache.commons:commons-collections4:4.1" + dependency "org.apache.commons:commons-text:1.9" + + dependency "commons-io:commons-io:2.11.0" + + dependency "com.google.guava:guava:31.0.1-jre" + + dependency "org.slf4j:slf4j-api:1.7.30" + dependency "org.apache.logging.log4j:log4j-api:2.17.1" + dependency "org.apache.logging.log4j:log4j-core:2.17.1" + dependency "org.apache.logging.log4j:log4j-slf4j-impl:2.17.1" + + dependency "com.lmax:disruptor:3.4.2" + + dependency "com.fasterxml.jackson.core:jackson-databind:2.13.0" + dependency "com.fasterxml.jackson.core:jackson-core:2.13.0" + dependency "com.fasterxml.jackson.core:jackson-annotations:2.13.0" + + dependency "org.asynchttpclient:async-http-client:2.12.0" + dependency "org.apache.httpcomponents:httpclient:4.5.13" + + dependency "io.netty:netty-all:4.1.79.Final" + + dependency 'io.dropwizard.metrics:metrics-core:4.1.0' + dependency "io.dropwizard.metrics:metrics-healthchecks:4.1.0" + dependency "io.dropwizard.metrics:metrics-annotation:4.1.0" + dependency "io.dropwizard.metrics:metrics-json:4.1.0" + + dependency 'io.opentelemetry:opentelemetry-api:1.3.0' + dependency 'io.opentelemetry:opentelemetry-sdk:1.3.0' + dependency 'io.opentelemetry:opentelemetry-sdk-metrics:1.3.0-alpha' + dependency 'io.opentelemetry:opentelemetry-exporter-prometheus:1.3.0-alpha' + dependency 'io.prometheus:simpleclient:0.8.1' + dependency 'io.prometheus:simpleclient_httpserver:0.8.1' + dependency 'io.opentelemetry:opentelemetry-exporter-zipkin:1.3.0' + dependency 'io.opentelemetry:opentelemetry-semconv:1.3.0-alpha' + dependency 'io.opentelemetry:opentelemetry-exporter-jaeger:1.4.0' + + dependency "io.openmessaging:openmessaging-api:2.2.1-pubsub" + + dependency "com.h3xstream.findsecbugs:findsecbugs-plugin:1.11.0" + dependency "com.mebigfatguy.fb-contrib:fb-contrib:7.4.7" + + dependency "org.springframework.boot:spring-boot-starter-web:2.6.7" + dependency "io.openmessaging:registry-server:0.0.1" + + dependency "junit:junit:4.13.2" + dependency "com.github.stefanbirkner:system-rules:1.16.1" + dependency "org.assertj:assertj-core:2.6.0" + + dependency "org.mockito:mockito-core:3.8.0" + dependency "org.mockito:mockito-inline:3.8.0" + dependency "org.powermock:powermock-module-junit4:2.0.2" + dependency "org.powermock:powermock-api-mockito2:2.0.2" + + dependency "io.cloudevents:cloudevents-core:2.2.0" + dependency "io.cloudevents:cloudevents-json-jackson:2.2.0" + + dependency "io.grpc:grpc-protobuf:${grpcVersion}" + dependency "io.grpc:grpc-stub:${grpcVersion}" + dependency "io.grpc:grpc-netty:${grpcVersion}" + dependency "io.grpc:grpc-netty-shaded:${grpcVersion}" + + dependency "javax.annotation:javax.annotation-api:1.3.2" + + dependency "com.github.seancfoley:ipaddress:5.3.3" + dependency "com.google.code.gson:gson:2.8.2" + + dependency "org.yaml:snakeyaml:1.30" + dependency "org.javassist:javassist:3.24.0-GA" + + dependency "com.alibaba.nacos:nacos-client:2.1.0" + + dependency 'org.apache.zookeeper:zookeeper:3.4.6' + dependency 'org.apache.curator:curator-client:4.0.1' + dependency 'org.apache.curator:curator-framework:4.0.1' + dependency 'org.apache.curator:curator-recipes:4.0.1' + dependency 'org.apache.curator:curator-test:2.12.0' + + dependency "org.projectlombok:lombok:1.18.22" + dependency "com.github.seancfoley:ipaddress:5.3.3" + dependency "javax.annotation:javax.annotation-api:1.3.2" + dependency "com.alibaba:fastjson:1.2.83" + } + } +} diff --git a/docker/centos7-jdk8/Dockerfile b/docker/centos7-jdk8/Dockerfile new file mode 100644 index 0000000000..7d968413d5 --- /dev/null +++ b/docker/centos7-jdk8/Dockerfile @@ -0,0 +1,31 @@ +# +# 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. +# + +FROM docker.io/centos:7 + +MAINTAINER mikexue + +RUN yum update -y && yum install net-tools -y && yum install lrzsz -y && yum install vim -y +ADD jdk-8u281-linux-x64.tar.gz /usr/local/src/ +RUN ln -s /usr/local/src/jdk1.8.0_281/ /usr/local/jdk + +ENV JAVA_HOME /usr/local/jdk +ENV JRE_HOME $JAVA_HOME/jre +ENV CLASSPATH .:$JAVA_HOME/lib/:$JRE_HOME/lib/ +ENV PATH $PATH:$JAVA_HOME/bin diff --git a/docker/eventmesh/Dockerfile b/docker/eventmesh/Dockerfile new file mode 100644 index 0000000000..6ea5944d19 --- /dev/null +++ b/docker/eventmesh/Dockerfile @@ -0,0 +1,35 @@ +# +# 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. +# + +FROM centos7-jdk8:latest + +MAINTAINER mikexue mike_xwm@126.com + +WORKDIR /data +RUN mkdir /data/app +ADD EventMesh_1.3.0-release.tar.gz /data/app/eventmesh +WORKDIR /data/app/eventmesh/bin + +EXPOSE 10000 +EXPOSE 10105 + +ENV DOCKER true + +CMD sh start.sh + diff --git a/docs/_config.yml b/docs/_config.yml deleted file mode 100644 index c4192631f2..0000000000 --- a/docs/_config.yml +++ /dev/null @@ -1 +0,0 @@ -theme: jekyll-theme-cayman \ No newline at end of file diff --git a/docs/cn/features/0-introduction.md b/docs/cn/features/0-introduction.md deleted file mode 100644 index 195054feb7..0000000000 --- a/docs/cn/features/0-introduction.md +++ /dev/null @@ -1,49 +0,0 @@ -# DeFiBus -       -**DeFiBus=RPC+MQ,是基于开源消息中间件打造的安全可靠的分布式金融级消息总线。DeFibus不仅提供了RPC同步调用,还提供了MQ的异步事件通知、事件组播和广播等常用服务调用和消息模式,同时增加了应用多中心多活、服务就近、灰度发布等分布式场景下的高可用能力。在对于机器故障的容错能力方面的增强,也让消息总线的服务更加稳定可靠,为业务提供7x24的服务。** - -### 整体架构 -
- -![architecture1](../../../docs/images/features/a-distributing-architecture-in-financial.png) - -
- -![architecture2](../../../docs/images/features/architecture-p1.png) - -DeFiBus主要包括以下几个组件(模块): - -* **Broker**:通过轻量的Topic和Queue机制提供消息存储功能。Broker定期将Topic信息上报到NameServer中,同集群中的Broker实例上报的NameServer必须保持一致,避免路由信息不一致。 - -* **NameServer**:NameServer提供Topic的发现和路由,每一个NameServer接受Broker上报的Topic信息,并维护Topic的路由信息供客户端查询。 - -* **GSL**:全局服务定位(Global Service Location)服务提供服务级别的路由发现。服务可以部署在不同的区域(比如不同的数据中心、逻辑分区等),服务请求方在请求某一个具体服务时,无需关注服务部署的区域,GSL能够根据服务发现规则自动定位到具体的服务,将服务信息返回给客户端。 - -* **SGS**:服务治理系统(Service Government System)负责全局的服务管理,包括服务的申请、服务部署规划、服务下线等服务全生命周期的管理。在DeFiBus中,服务与Topic一一对应,Topic的名称由对应的服务按照一定的规则来命名。Topic的创建、更新和删除由SGS统一管理。SGS在服务的部署区域对应的Broker集群中创建Topic之后,将更新全局服务路由数据,供GSL定位服务使用。 - -* **Proxy**:服务代理(Proxy)提供HTTP接入方式,同时允许按照协议规范开发的C、GO、Python等其他语言客户端的接入。 - -### 服务和Topic的定义 -       -DeFiBus把服务和Topic做了一一对应,每个服务必须对应一个Topic。Topic根据服务的唯一ID和服务的部署区域来命名。每个服务需要有服务的唯一标识,可以用数字ID或者字符串来表示。每个部署区域使用3位长度的字符串(限数字和字母构成)表示。 -Topic按照如下格式来命名: -``` -[区域代码]-[服务唯一ID] -``` - -比如,余额查询服务的服务ID为20190001表示,部署在“A10”这个区域,那么该服务在A10区域的Topic就命名为“A10-20190001”。Topic的命名规则 - - -### 特性列表: -* [RPC调用:即“Request-Reply”模式,支持系统间的同步调用](docs/cn/features/1-request-response-call.md) -* 消息发布/订阅:消息的发布和订阅 -* [灰度发布:服务级别的灰度发布](docs/cn/features/2-dark-launch.md) -* [熔断机制:应用实例级别的熔断](docs/cn/features/3-circuit-break-mechanism.md) -* [服务就近:就近进行服务的请求和响应,减少跨区调用](docs/cn/features/4-invoke-service-nearby.md) -* [应用多活:应用多中心多活](docs/cn/features/5-multi-active.md) -* [动态扩缩队列 :自适应应用实例数量,动态调整队列个数](docs/cn/features/6-dynamic-adjust-queue.md) -* [容错机制:故障和错误隔离](docs/cn/features/8-fault-tolerant.md) -* 服务路由和定位:动态路由及定位(后续开源) -* 服务代理:HTTP及多语言的代理(后续开源) -* 服务治理:服务元数据的管理(后续开源) -* 平滑升级:平滑升级、平滑扩容(后续开源) \ No newline at end of file diff --git a/docs/cn/features/1-request-response-call.md b/docs/cn/features/1-request-response-call.md deleted file mode 100644 index 1feabaf457..0000000000 --- a/docs/cn/features/1-request-response-call.md +++ /dev/null @@ -1,34 +0,0 @@ -## 1. Request-Reply同步调用 - -       -Request-Reply同步调用指的是请求方发出一条消息之后,需要响应方在消费完这条消息后回复一个响应结果。 - -
- -![RR](../../images/features/RR-call-p1.png) - -
- -整个调用过程包含了两个消息的产生和消费过程。 -**1.请求方产生请求消息,服务响应方消费这条请求消息** -       -请求方根据服务提供方的协议将请求内容设置到消息体中,并将消息发送到Broker上。服务响应方订阅相应的Topic,从Broker上获取到请求消息,并消费。 - -**2.服务响应方产生响应消息,请求方接收这条响应消息** -       -服务响应方收到请求消息后,执行相应的处理,并将请求结果设置到响应消息的消息体中,将响应消息发送到Broker上。请求方接收响应消息的方式采用的是Broker推送的形式,而不是由Producer订阅的方式,从而使得响应消息能够精准回到发出请求消息的实例上。 - -       -DeFiBus在每条请求消息中增加REPLY_TO属性来唯一标识每一个请求方实例。在创建响应消息时将REPLY_TO属性透传到响应消息中。Broker收到响应消息后,根据REPLY_TO属性,查找出对应的请求方实例的连接,将响应消息推送给该请求方实例。 - - ---- -#### Links: -* [架构介绍](../../../README.md) -* [Request-Reply调用](docs/cn/features/1-request-response-call.md) -* [灰度发布](docs/cn/features/2-dark-launch.md) -* [熔断机制](docs/cn/features/3-circuit-break-mechanism.md) -* [服务就近](docs/cn/features/4-invoke-service-nearby.md) -* [应用多活](docs/cn/features/5-multi-active.md) -* [动态扩缩队列](docs/cn/features/6-dynamic-adjust-queue.md) -* [容错机制](docs/cn/features/8-fault-tolerant.md) \ No newline at end of file diff --git a/docs/cn/features/10-flow-control.md b/docs/cn/features/10-flow-control.md deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs/cn/features/2-dark-launch.md b/docs/cn/features/2-dark-launch.md deleted file mode 100644 index e6e7e20119..0000000000 --- a/docs/cn/features/2-dark-launch.md +++ /dev/null @@ -1,24 +0,0 @@ -## 2.灰度发布 - -       -同一个消费组中的消费者实例通常订阅的Topic是相同的。在有新业务上线时,我们希望仅仅在个别实例上进行灰度,验证通过之后再进行全量。DeFiBus提供了灰度发布的能力,同一个消费组中,允许不同消费者实例订阅不同的Topic,只有订阅了某个具体Topic的实例才能够收到这个Topic的消息,同消费组中没有订阅这个Topic的实例不会收到消息。 - -       -假设一个消费组有3个消费者实例,上线初期只涉及到Topic1和Topic2。当业务扩展,需要增加Topic3的订阅时,可以先灰度其中一个实例,验证Topic3在灰度实例上执行正常之后,逐步再替换其他实例。在这期间,实例1和实例2不会收到Topic3的消息。 - -
- -![avater](../../images/features/dark-launch-p1.png) - -
- ---- -#### Links: -* [架构介绍](../../../README.md) -* [Request-Reply调用](docs/cn/features/1-request-response-call.md) -* [灰度发布](docs/cn/features/2-dark-launch.md) -* [熔断机制](docs/cn/features/3-circuit-break-mechanism.md) -* [服务就近](docs/cn/features/4-invoke-service-nearby.md) -* [应用多活](docs/cn/features/5-multi-active.md) -* [动态扩缩队列](docs/cn/features/6-dynamic-adjust-queue.md) -* [容错机制](docs/cn/features/8-fault-tolerant.md) \ No newline at end of file diff --git a/docs/cn/features/3-circuit-break-mechanism.md b/docs/cn/features/3-circuit-break-mechanism.md deleted file mode 100644 index 06eec22ae3..0000000000 --- a/docs/cn/features/3-circuit-break-mechanism.md +++ /dev/null @@ -1,25 +0,0 @@ -## 3.熔断 -       -DeFiBus基于队列来做消费端的负载均衡,对同一个消费组,除广播模式外,每个队列只由一个消费者实例消费。当一个实例处理能力下降或者异常出现消息堆积时,为了避免堆积情况继续加剧,DeFiBus会触发队列的熔断,此时生产者实例在感知到队列熔断之后,会优先把消息发送到其他没有熔断的队列上,暂停往熔断队列上写入新消息。当堆积消除后,熔断被解除,生产者恢复往该队列发送消息。 - -       -DeFiBus对每个Topic定义了深度的属性,表示Topic的队列允许堆积的最大消息条数。消息堆积数表示队列中尚未下发给消费者实例的消息条数,可由队列中最新一条消息的offset与消费者实例已经获取到的消息的offset的差值计算。 -
- -![offset](../../../docs/images/features/circuit-break-p1.png) - -
- -       -当Consumer出现异常或者触发了流控,Consumer拉消息过程受阻,队列的DeliverOffset停止不前,新消息持续写入,MaxOffset不断变大,最终MaxOffset与DeliverOffset将超过Topic的最大深度限制,触发队列熔断。 - ---- -#### Links: -* [架构介绍](../../../README.md) -* [Request-Reply调用](docs/cn/features/1-request-response-call.md) -* [灰度发布](docs/cn/features/2-dark-launch.md) -* [熔断机制](docs/cn/features/3-circuit-break-mechanism.md) -* [服务就近](docs/cn/features/4-invoke-service-nearby.md) -* [应用多活](docs/cn/features/5-multi-active.md) -* [动态扩缩队列](docs/cn/features/6-dynamic-adjust-queue.md) -* [容错机制](docs/cn/features/8-fault-tolerant.md) diff --git a/docs/cn/features/4-invoke-service-nearby.md b/docs/cn/features/4-invoke-service-nearby.md deleted file mode 100644 index 209940cbfd..0000000000 --- a/docs/cn/features/4-invoke-service-nearby.md +++ /dev/null @@ -1,29 +0,0 @@ -## 4.服务就近 -       -为了保证高可用,服务的部署通常分布在多个机房、区域。我们希望服务之间能够就近调用,减少跨机房跨区域网络访问的时延问题。对此,DeFiBus在Broker和客户端上都增加了区域的属性来标识实例属于哪个区域。对于Producer,消息会优先发往同区域内的Broker集群上;对于Consumer,则优先监听同区域内的Queue;当一个区域内没有Consumer实例监听时,则由其他区域的Consumer实例跨区域监听。 - -### 就近发送 -       -在创建Producer时,通过设置```DeFiBusClientConfig.setClusterPrefix("your region")```来标识Producer实例所在的区域。Producer在每次发送消息会先选则一个Queue来作为发送的目标队列。当启用就近发送时,Producer优先选择与自己同区域内的Queue,当本区域内没有可用Queue时,则选择其他区域的Queue。 -
- -
- -### 就近监听 -       -就近监听指的是Consumer在做负载均衡分配Queue的时候,每个区域内的Queue只由该区域内的Consumer监听和消费,当且仅当一个区域内没有订阅该Topic的Consumer时,由其他区域订阅了该Topic的Consumer跨区域监听和消费这些Queue。虽然Consumer是在同区域内就近消费,但仍通过心跳维持跨区域的连接,以保证能够随时跨区域接管消费。 - -
- -
- ---- -#### Links: -* [架构介绍](../../../README.md) -* [Request-Reply调用](docs/cn/features/1-request-response-call.md) -* [灰度发布](docs/cn/features/2-dark-launch.md) -* [熔断机制](docs/cn/features/3-circuit-break-mechanism.md) -* [服务就近](docs/cn/features/4-invoke-service-nearby.md) -* [应用多活](docs/cn/features/5-multi-active.md) -* [动态扩缩队列](docs/cn/features/6-dynamic-adjust-queue.md) -* [容错机制](docs/cn/features/8-fault-tolerant.md) \ No newline at end of file diff --git a/docs/cn/features/5-multi-active.md b/docs/cn/features/5-multi-active.md deleted file mode 100644 index f24366630b..0000000000 --- a/docs/cn/features/5-multi-active.md +++ /dev/null @@ -1,18 +0,0 @@ -## 5.同城多中心多活 -       -同城多中心多活指的是应用的多活,在DeFiBus集群正常运行的情况下,应用部署在多个数据中心,一个数据中心的应用实例全部挂掉后,DeFiBus能够自动将应用流量切换到另一个数据中心的应用实例上,保证应用能够持续稳定地提供服务而不中断。同城多中心多活得益于DeFiBus的服务就近特性,结合应用部署的规划,使得正常情况下服务调用发生在同一个数据中心,当一个中心的应用出现故障时,能够有其他中心的实例接管服务。 - -
- -
- ---- -#### Links: -* [架构介绍](../../../README.md) -* [Request-Reply调用](docs/cn/features/1-request-response-call.md) -* [灰度发布](docs/cn/features/2-dark-launch.md) -* [熔断机制](docs/cn/features/3-circuit-break-mechanism.md) -* [服务就近](docs/cn/features/4-invoke-service-nearby.md) -* [应用多活](docs/cn/features/5-multi-active.md) -* [动态扩缩队列](docs/cn/features/6-dynamic-adjust-queue.md) -* [容错机制](docs/cn/features/8-fault-tolerant.md) \ No newline at end of file diff --git a/docs/cn/features/6-dynamic-adjust-queue.md b/docs/cn/features/6-dynamic-adjust-queue.md deleted file mode 100644 index 9c27b7deb1..0000000000 --- a/docs/cn/features/6-dynamic-adjust-queue.md +++ /dev/null @@ -1,35 +0,0 @@ -## 自动伸缩Queue -       -在同一个消费组内,每个队列只由一个实例消费。当队列数小于消费者实例数时,会有部分消费者实例分不到队列;反之,当队列数大于消费者实例数时,每个消费者需要消费多个队列。队列数不是消费者实例数的整数倍时,则会出现部分实例需要消费比同组内的其他实例更多的队列,出现负载不均衡问题。 - -       -DeFiBus提供了队列数量自动调整的特性。当有Consumer新注册或者去注册时,Broker触发队列的自动伸缩,根据当前在线的消费者实例个数,增加或者减少队列个数,使队列个数与消费者实例数保持一致。 - -       -当队列数需要增加时,首先调整Topic的ReadQueueNum,将可读的队列数扩增;10s之后,再调整Topic的WriteQueueNum,将可写的队列数扩增。这样使得新扩增的队列能够先被消费者感知并监听上,然后才让生产者感知到,往新队列上发送消息,是扩增操作更平滑。 - -
- -
- -       -当队列数需要减少时,首先调整Topic的WriteQueueNum,将可写的队列数缩减;5分钟(默认,可配置)后先检查即将被缩减的队列中是否有消息没有被消费完,如果有,则继续延迟缩减操作,使消费者能够继续消费完队列中的消息;如果没有,则调整ReadQueueNum,将可写的队列数缩减。 - -
- -
- -       -对于多个消费组订阅相同Topic并且是集群消费模式时,在计算扩缩的队列个数时,以最大的消费组的消费者实例数为准,保证拥有最多实例数的消费组内每个消费者实例都能够分到Queue进行消费。 - - ---- -#### Links: -* [架构介绍](../../../README.md) -* [Request-Reply调用](docs/cn/features/1-request-response-call.md) -* [灰度发布](docs/cn/features/2-dark-launch.md) -* [熔断机制](docs/cn/features/3-circuit-break-mechanism.md) -* [服务就近](docs/cn/features/4-invoke-service-nearby.md) -* [应用多活](docs/cn/features/5-multi-active.md) -* [动态扩缩队列](docs/cn/features/6-dynamic-adjust-queue.md) -* [容错机制](docs/cn/features/8-fault-tolerant.md) \ No newline at end of file diff --git a/docs/cn/features/7-isolation-mechanism.md b/docs/cn/features/7-isolation-mechanism.md deleted file mode 100644 index 298efc461d..0000000000 --- a/docs/cn/features/7-isolation-mechanism.md +++ /dev/null @@ -1,23 +0,0 @@ -## 隔离机制 -Producer在往Topic发送消息时,会按照MessageQueueSelector定义的选择策略,从Topic的所有MessageQueue中选择一个作为目标队列发送消息。 -当队列发生熔断,或者Broker故障导致队列发送消息异常时,如果没有对这些队列进行特殊处理,下次再轮到发这个队列的时候仍然可能失败。 - -DeFiBus提供异常队列的隔离机制,当往某个队列发送消息失败时,将队列标记为隔离状态,在隔离过期之前将不再往这个队列发送消息,避免再次失败,降低失败概率。 - -异常队列隔离机制分为两步: -**-发现并标记队列为隔离** -在发送回调中更新发送队列的健康状态,如果执行的是onSuccess分支,则标记队列为健康,去除队列的隔离标记;如果执行的是onException分支,则标记队列为隔离状态。 - -**-不选择隔离中的队列发送消息** -在MessageQueueSelector中实现隔离机制的过滤逻辑,每次进行队列的选择时,优先从没有标记为隔离的队列中选择。当所有队列都被标记为隔离时,则从所有队列中选择,保证每次都要选出一个队列。 - ---- -#### Links: -* [架构介绍](../../../README.md) -* [Request-Reply调用](docs/cn/features/1-request-response-call.md) -* [灰度发布](docs/cn/features/2-dark-launch.md) -* [熔断机制](docs/cn/features/3-circuit-break-mechanism.md) -* [服务就近](docs/cn/features/4-invoke-service-nearby.md) -* [应用多活](docs/cn/features/5-multi-active.md) -* [动态扩缩队列](docs/cn/features/6-dynamic-adjust-queue.md) -* [容错机制](docs/cn/features/8-fault-tolerant.md) \ No newline at end of file diff --git a/docs/cn/features/8-fault-tolerant.md b/docs/cn/features/8-fault-tolerant.md deleted file mode 100644 index f118c9d311..0000000000 --- a/docs/cn/features/8-fault-tolerant.md +++ /dev/null @@ -1,50 +0,0 @@ -## 8.容错机制 -       -在金融场景下,对可用性和稳定性的要求非常高,中间件对机器故障、网络故障、应用故障以及中间件本身的故障等常见故障场景需要有容错能力,降低故障带来的影响。 - -### 隔离机制 -##### 1. Producer端的隔离 -       -Producer在往Topic发送消息时,会按照MessageQueueSelector定义的选择策略,从Topic的所有MessageQueue中选择一个作为目标队列发送消息。 -当队列发生熔断,或者Broker故障导致队列发送消息异常时,如果没有对这些队列进行特殊处理,下次再轮到发这个队列的时候仍然可能失败。 - -       -DeFiBus提供异常队列的隔离机制,当往某个队列发送消息失败时,将队列标记为隔离状态,在隔离过期之前将不再往这个队列发送消息,避免再次失败,降低失败概率。 - -异常队列隔离机制分为两步: -**-发现并标记队列为隔离** -       -在发送回调中更新发送队列的健康状态,如果执行的是onSuccess分支,则标记队列为健康,去除队列的隔离标记;如果执行的是onException分支,则标记队列为隔离状态。 - -**-不选择隔离中的队列发送消息** -       -在MessageQueueSelector中实现隔离机制的过滤逻辑,每次进行队列的选择时,优先从没有标记为隔离的队列中选择。当所有队列都被标记为隔离时,则从所有队列中选择,保证每次都要选出一个队列。 - - -##### 2. Consumer端的隔离 - -       -Consumer由拉消息线程只负责把拉消息请求以异步发送的形式发送出去。在正常情况下,每次拉消息请求的执行都很快,不会有卡顿。一旦有Broker故障导致PullRequest的执行发生了卡顿,则该Consumer监听的所有Queue都会因为PullRequest执行的延迟而出现消息消费延迟。对于RR同步请求的场景,这种是不能够接受的。 - -       -创建连接采用的是同步建立连接的策略,线程执行创建新连接时必须等待连接创建完成或者连接超时。当有Broker故障连不上时,就算是异步发送,也会因为同步等待连接建立而阻塞。此时就会出现一个Broker的故障导致其他健康Broker的消息消费出现延迟。 - -       -DeFiBus在Consumer拉消息的过程中增加了对拉消息任务的隔离,此处的隔离指的是将疑似有问题的任务隔离到另外的线程中执行,保证拉消息线程能够正常处理其他正常的任务。当发现执行拉消息耗时超过设定的阈值时,将该拉消息任务对应的Broker列入“隔离名单”中,在隔离过期之前,隔离Broker的拉消息请求都转交给另外线程执行,避免阻塞拉消息主线程,从而避免故障的Broker影响健康Broker的消息消费时效。 - -### 连接空闲机制 - -       -当连接的读或者写空闲超过60秒时,将主动断开连接。 - - ---- -#### Links: -* [架构介绍](../../../README.md) -* [Request-Reply调用](docs/cn/features/1-request-response-call.md) -* [灰度发布](docs/cn/features/2-dark-launch.md) -* [熔断机制](docs/cn/features/3-circuit-break-mechanism.md) -* [服务就近](docs/cn/features/4-invoke-service-nearby.md) -* [应用多活](docs/cn/features/5-multi-active.md) -* [动态扩缩队列](docs/cn/features/6-dynamic-adjust-queue.md) -* [容错机制](docs/cn/features/8-fault-tolerant.md) \ No newline at end of file diff --git a/docs/cn/features/9-publish-type.md b/docs/cn/features/9-publish-type.md deleted file mode 100644 index 74c3446d77..0000000000 --- a/docs/cn/features/9-publish-type.md +++ /dev/null @@ -1,35 +0,0 @@ -## 2. 单播、多播、广播 - -       -DeFiBus支持单播、多播、广播消费模式。 - -### 单播 - -
- -![unicast](../../images/features/unicast.png) - -
- -单播模式下,topic只被一个消费组监听;接收消息时,消费组内有且仅有一个实例会收到消息。 - -### 多播 - -
- -![multicast](../../images/features/multicast.png) - -
- -多播模式下,topic被多个消费组监听;接收消息时,每个消费组内有且仅有一个实例会收到消息。 - - -### 广播 - -
- -![broadcast](../../images/features/broadcast.png) - -
- -广播模式下,监听此topic的每个消费组中的每个实例都需要收到消息。 \ No newline at end of file diff --git a/docs/cn/quickstart.md b/docs/cn/quickstart.md deleted file mode 100644 index bcff7fc088..0000000000 --- a/docs/cn/quickstart.md +++ /dev/null @@ -1,36 +0,0 @@ -# Quick start Instarction - -### dependencies -``` -64bit OS, Linux/Unix/Mac is recommended; -64bit JDK 1.8+; -Gradle 3.x; -4g+ free disk for Broker server -``` - -### download and build - -``` -download from git -unzip defibus-master.zip -cd defibus-master -gradle clean dist tar -x test - -You can get a tar.gz package in directory named 'build' -``` - -### Deployment - -deploy DeFiBusNamesrv -``` -tar -zxvf DeFiBus_1.0.0.tar.gz -cd bin -sh runnamesrv.sh -``` - -deploy DeFiBusBroker -``` -tar -zxvf DeFiBus_1.0.0.tar.gz -cd bin -sh runbroker.sh -``` diff --git a/docs/en/contribute/01-release.md b/docs/en/contribute/01-release.md new file mode 100644 index 0000000000..0810a75772 --- /dev/null +++ b/docs/en/contribute/01-release.md @@ -0,0 +1,731 @@ +# Release Creation Process + +:::caution +The documentation of Release Creation Process is WIP (Work-in-Progress). +::: + +## 理解 Apache 发布的内容和流程 + +Source Release 是 Apache 关注的重点,也是发布的必须内容;而 Binary Release 是可选项, + +请参考以下链接,找到更多关于 ASF 的发布指南: + +- [Apache Release Guide](http://www.apache.org/dev/release-publishing) +- [Apache Release Policy](http://www.apache.org/dev/release.html) +- [Maven Release Info](http://www.apache.org/dev/publishing-maven-artifacts.html) + + +## 本地构建环境准备 + +主要包括签名工具、Maven 仓库认证相关准备 + +### 1.安装GPG + +在[GnuPG官网](https://www.gnupg.org/download/index.html)下载安装包。GnuPG的1.x版本和2.x版本的命令有细微差别,下列说明以**GnuPG-2.x**版本为例 + +```sh +$ gpg --version #检查版本,应该为2.x +``` + +### 2.用gpg生成key + +根据提示,生成 key + +> 注意:请使用Apache邮箱生成GPG的Key + +```shell +$ gpg --full-gen-key +gpg (GnuPG) 2.0.12; Copyright (C) 2009 Free Software Foundation, Inc. +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + +Please select what kind of key you want: + (1) RSA and RSA (default) + (2) DSA and Elgamal + (3) DSA (sign only) + (4) RSA (sign only) +Your selection? 1 +RSA keys may be between 1024 and 4096 bits long. +What keysize do you want? (2048) 4096 +Requested keysize is 4096 bits +Please specify how long the key should be valid. + 0 = key does not expire + = key expires in n days + w = key expires in n weeks + m = key expires in n months + y = key expires in n years +Key is valid for? (0) +Key does not expire at all +Is this correct? (y/N) y + +GnuPG needs to construct a user ID to identify your key. + +Real name: ${输入用户名} +Email address: ${邮箱地址} +Comment: CODE SIGNING KEY +You selected this USER-ID: + "${输入用户名} (CODE SIGNING KEY) <${邮箱地址}>" + +Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O +You need a Passphrase to protect your secret key. # 填入密码,以后打包过程中会经常用到 +``` + +### 3.查看 key + +```shell +$ gpg --list-keys +pub rsa4096/579C25F5 2021-04-26 # 579C25F5就是key id +uid [ultimate] ${输入用户名} <${邮箱地址}> +sub rsa4096 2021-04-26 + +# 通过key id发送public key到keyserver +$ gpg --keyserver pgpkeys.mit.edu --send-key 579C25F5 +# 其中,pgpkeys.mit.edu为随意挑选的keyserver,keyserver列表为:https://sks-keyservers.net/status/,相互之间是自动同步的,选任意一个都可以。 +$ gpg --keyserver hkp://pgpkeys.mit.edu --recv-keys 579C25F5 # 验证是否同步到公网,网络不好可能需多试几次 +``` + +**注:如果有多个 public key,设置默认 key。**修改`~/.gnupg/gpg.conf` + +```sh +# If you have more than 1 secret key in your keyring, you may want to +# uncomment the following option and set your preferred keyid. +default-key 28681CB1 +``` + +**如果有多个 public key, 也可以删除无用的 key:** + +```shell +$ gpg --delete-secret-keys 29BBC3CB # 先删除私钥,指明key id +gpg (GnuPG) 2.2.27; Copyright (C) 2021 g10 Code GmbH +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + +sec rsa4096/EE8DAE7D29BBC3CB 2021-04-27 mikexue + +Delete this key from the keyring? (y/N) y +This is a secret key! - really delete? (y/N) y +``` + +```shell +$ gpg --delete-keys 29BBC3CB # 删除公钥,指明key id +gpg (GnuPG) 2.2.27; Copyright (C) 2021 g10 Code GmbH +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + + +pub rsa4096/EE8DAE7D29BBC3CB 2021-04-27 mikexue + +Delete this key from the keyring? (y/N) y +``` + +由于公钥服务器没有检查机制,任何人都可以用你的名义上传公钥,所以没有办法保证服务器上的公钥的可靠性。 通常,你可以在网站上公布一个公钥指纹,让其他人核对下载到的公钥是否为真。 + +```shell +# fingerprint参数生成公钥指纹: +$gpg --fingerprint mikexue +pub rsa4096 2021-04-26 [SCA] + F84A 0041 D70B 37AF 9C7B F0B3 39F4 29D7 579C 25F5 +uid [ultimate] mikexue +sub rsa4096 2021-04-26 [E] +``` + +登录 [https://id.apache.org](https://id.apache.org/), 将上面的 fingerprint (即 F84A 0041 D70B 37AF 9C7B F0B3 39F4 29D7 579C 25F5) 粘贴到自己的用户信息中 OpenPGP Public Key Primary Fingerprint + + + +## 发布Apache Maven仓库 + +> 注:EventMesh使用Gradle构建,需修改gradle相关配置 + +### 1.导出私钥文件 + +```shell +$ gpg --export-secret-keys -o secring.gpg #私钥文件妥善保管,后面配置需要 +``` + +### 2.准备分支 + +从主干分支拉取新分支作为发布分支,如现在要发布$`{release_version}`版本,则从develop分支拉出新分支`${release_version}-release`,此后`${release_version}` Release Candidates涉及的修改及打标签等都在`${release_version}-release`分支进行,最终发布完成后合入主干分支。 + +### 3.更新版本说明 + +更新官网项目的如下文件,并提交至master分支: + +https://github.com/apache/incubator-eventmesh-site/tree/master/events/release-notes + +### 4.配置根项目下gradle.properties文件 + +```shell +group=org.apache.eventmesh +version=1.2.0-release +#40位公钥的最后8位 +signing.keyId=579C25F5 +#生成密钥时填的passphrase +signing.password= +#导出的私钥文件secring.gpg路径 +signing.secretKeyRingFile=../secring.gpg +#apache 账号 +apacheUserName= +#apache 密码 +apachePassWord= +``` + +### 5.检查子模块下gradle.properties文件 + +```shell +group=org.apache.eventmesh +version=${release_version} +``` + +### 6.检查并配置根项目下build.gradle文件 + +```shell +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + artifact packageSources + artifact packageJavadoc + versionMapping { + usage('java-api') { + fromResolutionOf('runtimeClasspath') + } + usage('java-runtime') { + fromResolutionResult() + } + } + pom { + name = 'EventMesh' + description = 'Apache EventMesh' + url = 'https://github.com/apache/incubator-eventmesh' + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + developers { + developer { + id = 'Apache EventMesh(incubating)' + name = 'Apache EventMesh(incubating) of ASF' + url = 'https://eventmesh.apache.org/' + } + } + scm { + connection = 'scm:git:git@github.com:apache/incubator-eventmesh.git' + developerConnection = 'scm:git:git@github.com:apache/incubator-eventmesh.git' + url = 'https://github.com/apache/incubator-eventmesh' + } + } + } + } + repositories { + maven { + def releasesRepoUrl = 'https://repository.apache.org/service/local/staging/deploy/maven2/' + def snapshotsRepoUrl = 'https://repository.apache.org/content/repositories/snapshots/' + url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl + credentials { + username apacheUserName + password apachePassWord + } + + } + } +} + +signing { + sign publishing.publications.mavenJava +} +``` + +### 7.上传发布包 + +执行如下命令,需要对jar、源码包、doc和pom等文件签名加密 + +```shell +$ gradle signMavenJavaPublication publish +``` + +上述命令执行成功后,待发布版本会自动上传到Apache的临时筹备仓库(staging repository)。所有被deploy到远程[maven仓库](http://repository.apache.org/)的Artifacts都会处于staging状态,访问https://repository.apache.org/#stagingRepositories, 使用Apache的LDAP账户登录后,就会看到上传的版本,`Repository`列的内容即为${STAGING.REPOSITORY}。 点击`Close`来告诉Nexus这个构建已经完成,只有这样该版本才是可用的。 如果电子签名等出现问题,`Close`会失败,可以通过`Activity`查看失败信息。 + + + +## 发布Apache SVN仓库 + +### 1.准备svn本机环境(Apache使用svn托管项目的发布内容) + +### 2.checkout到本地目录 + +```shell +$ svn checkout https://dist.apache.org/repos/dist/dev/incubator/eventmesh/ +# 假定本地目录为 ~/apache/eventmesh +``` + +### 3.添加gpg公钥 + +添加public key到[KEYS](https://dist.apache.org/repos/dist/dev/incubator/eventmesh/KEYS)文件并提交到SVN仓库(第一次做发布的人需要做这个操作,具体操作参考KEYS文件里的说明)。KEYS主要是让参与投票的人在本地导入,用来校验sign的正确性 + +Windows + +```sh +$ gpg --list-sigs | out-file -append KEYS -encoding utf8 +$ gpg --armor --export | out-file -append KEYS -encoding utf8 +``` + +> Mac OS/Linux + +```sh +$ (gpg --list-sigs && gpg --armor --export ) >> KEYS +``` + +### 4.添加待发布内容到SVN目录 + +```shell +$ cd ~/apache/eventmesh # eventmesh svn根目录 +$ mkdir ${release_version}-${rc_version} +``` + +#### 4.1 创建tag + +在`${release_version}-release`分支上创建tag,需带有rc版本,为预发布版本 + +```shell +$ git tag -a v{$release_version}-{$rc_version} -m "Tagging the ${release_version} first Release Candidate (Candidates start at zero)" +$ git push origin --tags +``` + +#### 4.2 打包源码 + +检查项目源码命名,将源码命名为`apache-eventmesh-${release_version}-incubating-src`,将源码打包为tar.gz格式 + +```shell +$ tar -czvf apache-eventmesh-${release_version}-incubating-source.tar.gz apache-eventmesh-${release_version}-incubating-src +``` + +#### 4.3 打包二进制 + +> 编译上一步打包的源码 + +检查编译后的文件命名,将二进制文件命名为`apache-eventmesh-${release_version}-incubating` + +> 注:需将源码根目录下的`NOTICE`文件,`DISCLAIMER-WIP`文件以及`tools/third-party-licenses`目录下的`LICENSE`文件拷贝到二进制的包中 + +```shell +$ gradle clean jar dist && gradle installPlugin && gradle tar -x test +$ tar -czvf apache-eventmesh-${release_version}-incubating-bin.tar.gz apache-eventmesh-${release_version}-incubating +``` + +压缩source包、bin包,并将相关的压缩包拷贝到svn本地仓库下`/apache/eventmesh/${release_version}-${rc_version}` + +### 5.生成签名/sha512文件 + +> 针对源码包与二进制包生成签名/sha512文件 + +```shell +$ for i in *.tar.gz; do echo $i; gpg --print-md SHA512 $i > $i.sha512 ; done #计算sha512 +$ for i in *.tar.gz; do echo $i; gpg --armor --output $i.asc --detach-sig $i ; done #计算签名 +``` + +### 6.提交到Apache svn + +```shell +$ cd ~/apache/eventmesh # eventmesh svn根目录 +$ svn status +$ svn commit -m 'prepare for ${release_version}-${rc_version}' +``` + + + +## 验证Release Candidates + +详细检查列表请参考官方的[check list](https://cwiki.apache.org/confluence/display/INCUBATOR/Incubator+Release+Checklist) + +从以下地址下载要发布的Release Candidates到本地环境: + +```shell +https://dist.apache.org/repos/dist/dev/incubator/eventmesh/${release_version}-${rc_version}/ +``` + +然后开始验证环节,验证包含但不限于以下内容和形式 + +### 1.检查签名和hash等信息 + +> 由于操作系统不同,检查的命令或有差异,具体可参考[官方检查步骤](https://www.apache.org/info/verification.html) + +#### 1.1检查sha512哈希 + +> Mac OS/Linux + +```shell +$ shasum -a apache-eventmesh-${release_version}-incubating-source.tar.gz +#并将输出内容与 apache-eventmesh-${release_version}-${rc_version}-incubating-source.tar.gz.sha512文件内容作对比 +$ shasum -a apache-eventmesh-${release_version}-incubating-bin.tar.gz +#并将输出内容与 apache-eventmesh-${release_version}-${rc_version}-incubating-bin.tar.gz.sha512文件内容作对比 +``` + +> Windows + +```shell +$ certUtil -hashfile apache-eventmesh-${release_version}-incubating-source.tar.gz SHA512 +#并将输出内容与 apache-eventmesh-${release_version}-${rc_version}-incubating-source.tar.gz.sha512文件内容作对比 +$ certUtil -hashfile apache-eventmesh-${release_version}-incubating-bin.tar.gz SHA512 +#并将输出内容与 apache-eventmesh-${release_version}-${rc_version}-incubating-bin.tar.gz.sha512文件内容作对比 +``` + +#### 1.2检查gpg签名 + +首先导入发布人公钥。从svn仓库导入KEYS到本地环境。(发布版本的人不需要再导入,帮助做验证的人需要导入,用户名填发版人的即可) + +```shell +$ curl https://dist.apache.org/repos/dist/dev/incubator/eventmesh/KEYS >> KEYS +$ gpg --import KEYS +$ gpg --edit-key "${发布人的gpg用户名}" + > trust + +Please decide how far you trust this user to correctly verify other users' keys +(by looking at passports, checking fingerprints from different sources, etc.) + + 1 = I don't know or won't say + 2 = I do NOT trust + 3 = I trust marginally + 4 = I trust fully + 5 = I trust ultimately + m = back to the main menu + +Your decision? 5 + + > save +``` + +然后使用如下命令检查签名 + +```shell +$ gpg --verify apache-eventmesh-${release_version}-incubating-source.tar.gz.asc apache-eventmesh-${release_version}-incubating-source-tar.gz +$ gpg --verify apache-eventmesh-${release_version}-incubating-bin.tar.gz.asc apache-eventmesh-${release_version}-incubating-bin.tar.gz +``` + +### 2.检查源码包的文件内容 + +解压缩`apache-eventmesh-${release_version}-incubating-source-tar.gz`,进行如下检查: + +- 检查源码包是否包含由于包含不必要文件,致使tar包过于庞大 +- 文件夹包含单词`incubating` +- 存在`LICENSE`和`NOTICE`文件 +- 存在`DISCLAIMER`文件 +- `NOTICE`文件中的年份正确 +- 只存在文本文件,不存在二进制文件 +- 所有文件的开头都有ASF许可证 +- 能够正确编译,单元测试可以通过 (./gradle build) (目前支持JAVA 8/gradle 7.0/idea 2021.1.1及以上) +- 检查是否有多余文件或文件夹,例如空文件夹等 + +### 3.检查二进制包的文件内容 + +- 文件夹包含单词`incubating` +- 存在`LICENSE`和`NOTICE`文件 +- 存在`DISCLAIMER`文件 +- `NOTICE`文件中的年份正确 +- 所有文本文件开头都有ASF许可证 +- 检查第三方依赖许可证: + - 第三方依赖的许可证兼容 + - 所有第三方依赖的许可证都在`LICENSE`文件中声名 + - 依赖许可证的完整版全部在`license`目录 + - 如果依赖的是Apache许可证并且存在`NOTICE`文件,那么这些`NOTICE`文件也需要加入到版本的`NOTICE`文件中 + +你可以参考此文章:[ASF第三方许可证策](https://apache.org/legal/resolved.html) + +## 发起投票 + +> EventMesh 仍在孵化阶段,需要进行两次投票 + +- EventMesh社区投票,发送邮件至:`dev@eventmesh.apache.org` +- incubator社区投票,发送邮件至:`general@incubator.apache.org` EventMesh毕业后,只需要在EventMesh社区投票 + +### 1.EventMesh社区投票阶段 + +1. EventMesh社区投票,发起投票邮件到`dev@eventmesh.apache.org`。PMC需要先按照文档检查版本的正确性,然后再进行投票。 经过至少72小时并统计到3个`+1 PMC member`票后,即可进入下一阶段的投票。 +2. 宣布投票结果,发起投票结果邮件到`dev@eventmesh.apache.org`。 + +### 2.EventMesh社区投票模板 + +标题: + +``` +[VOTE] Release Apache EventMesh (incubating) ${release_version} ${rc_version} +``` + +正文: + +``` +Hello EventMesh Community, + + This is a call for vote to release Apache EventMesh (incubating) version ${release_version}-${rc_version}. + + Release notes: + https://github.com/apache/incubator-eventmesh/releases/tag/v${release_version}-${rc_version} + + The release candidates: + https://dist.apache.org/repos/dist/dev/incubator/eventmesh/${release_version}-${rc_version}/ + + Maven artifacts are available in a staging repository at: + https://repository.apache.org/content/repositories/orgapacheeventmesh-{staging-id} + + Git tag for the release: + https://github.com/apache/incubator-eventmesh/tree/v${release_version}-${rc_version} + + Keys to verify the Release Candidate: + https://downloads.apache.org/incubator/eventmesh/KEYS + + Hash for the release tag: + #hashCode of this release tag + + GPG user ID: + ${YOUR.GPG.USER.ID} + + The vote will be open for at least 72 hours or until necessary number of votes are reached. + + Please vote accordingly: + + [ ] +1 approve + + [ ] +0 no opinion + + [ ] -1 disapprove with the reason + + Checklist for reference: + + [ ] Download links are valid. + + [ ] Checksums and PGP signatures are valid. + + [ ] Source code distributions have correct names matching the current release. + + [ ] LICENSE and NOTICE files are correct for each EventMesh repo. + + [ ] All files have license headers if necessary. + + [ ] No compiled archives bundled in source archive. + + More detail checklist please refer: + https://cwiki.apache.org/confluence/display/INCUBATOR/Incubator+Release+Checklist + +Thanks, +Your EventMesh Release Manager +``` + +### 3.宣布投票结果模板 + +标题: + +``` +[RESULT][VOTE] Release Apache EventMesh (incubating) ${release_version} ${rc_version} +``` + +正文: + +``` +Hello Apache EventMesh PPMC and Community, + + The vote closes now as 72hr have passed. The vote PASSES with + + xx (+1 non-binding) votes from the PPMC, + xx (+1 binding) votes from the IPMC, + xx (+1 non-binding) votes from the rest of the developer community, + and no further 0 or -1 votes. + + The vote thread: {vote_mail_address} + + I will now bring the vote to general@incubator.apache.org to get approval by the IPMC. + If this vote passes also, the release is accepted and will be published. + +Thank you for your support. +Your EventMesh Release Manager +``` + +### 4.Incubator社区投票阶段 + +1. Incubator社区投票,发起投票邮件到`general@incubator.apache.org`,需3个 `+1 IPMC Member`投票,方可进入下一阶段。 +2. 宣布投票结果,发起投票结果邮件到`general@incubator.apache.org` 并抄送至`dev@eventmesh.apache.org`。 + +### 5.Incubator社区投票模板 + +标题: + +``` +[VOTE] Release Apache EventMesh (incubating) ${release_version} ${rc_version} +``` + +内容: + +``` +Hello Incubator Community, + + This is a call for a vote to release Apache EventMesh(Incubating) version ${release_version} ${rc_version} + + The Apache EventMesh community has voted on and approved a proposal to release + Apache EventMesh(Incubating) version ${release_version} ${rc_version} + + We now kindly request the Incubator PMC members review and vote on this + incubator release. + + EventMesh community vote thread: + • [投票链接] + + Vote result thread: + • [投票结果链接] + + The release candidate: + •https://dist.apache.org/repos/dist/dev/incubator/eventmesh/${release_version}-${rc_version}/ + + Git tag for the release: + • https://github.com/apache/incubator-eventmesh/tree/${release_version}-${rc_version} + Release notes: + • https://github.com/apache/incubator-eventmesh/releases/tag/${release_version}-${rc_version} + + The artifacts signed with PGP key [填写你个人的KEY], corresponding to [填写你个人的邮箱], that can be found in keys file: + • https://downloads.apache.org/incubator/eventmesh/KEYS + + The vote will be open for at least 72 hours or until necessary number of votes are reached. + + Please vote accordingly: + + [ ] +1 approve + [ ] +0 no opinion + [ ] -1 disapprove with the reason + +Thanks, +On behalf of Apache EventMesh(Incubating) community +``` + +### 6.宣布投票结果模板 + +标题: + +``` +[RESULT][VOTE] Release Apache EventMesh (incubating) ${release_version} ${rc_version} +``` + +内容: + +``` +Hi all, + + Thanks for reviewing and voting for Apache EventMesh(Incubating) version ${release_version} ${rc_version} release, I am happy to announce the release voting has passed with [投票结果数] binding votes, no +0 or -1 votes. + + Binding votes are from IPMC + - xxx + - xxx + - xxx + + Non-binding votes: + +1 xxx + +0 xxx + -1 xxx + + The voting thread is: + • [投票结果链接] + + Many thanks for all our mentors helping us with the release procedure, and all IPMC helped us to review and vote for Apache EventMesh(Incubating) release. I will be working on publishing the artifacts soon. + +Thanks, +On behalf of Apache EventMesh(Incubating) community +``` + +## 正式发布 + +### 1.合并分支 + +合并`${release_version}-release`分支的改动到`master`分支,合并完成后删除`release`分支 + +```shell +$ git checkout master +$ git merge origin/${release_version}-release +$ git pull +$ git push origin master +$ git push --delete origin ${release_version}-release +$ git branch -d ${release_version}-release +``` + +### 2.迁移源码与二进制包 + +将源码和二进制包从svn的`dev`目录移动到`release`目录 + +```shell +$ svn mv https://dist.apache.org/repos/dist/dev/incubator/eventmesh/${release_version}-${rc_version} https://dist.apache.org/repos/dist/release/incubator/eventmesh/ -m "transfer packages for ${release_version}-${rc_version}" #移动源码包与二进制包 +$ svn delete https://dist.apache.org/repos/dist/release/incubator/eventmesh/KEYS -m "delete KEYS" #清除原有release目录下的KEYS +$ svn cp https://dist.apache.org/repos/dist/dev/incubator/eventmesh/KEYS https://dist.apache.org/repos/dist/release/incubator/eventmesh/ -m "transfer KEYS for ${release_version}-${rc_version}" #拷贝dev目录KEYS到release目录 +``` + +### 3.确认dev和release下的包是否正确 + +- 确认[dev](https://dist.apache.org/repos/dist/dev/incubator/eventmesh/)下的`${release_version}-${rc_version}`已被删除 +- 删除[release](https://dist.apache.org/repos/dist/release/incubator/eventmesh/)目录下上一个版本的发布包,这些包会被自动保存在[这里](https://archive.apache.org/dist/incubator/eventmesh/) + +```shell +$ svn delete https://dist.apache.org/repos/dist/release/incubator/eventmesh/${last_release_version} -m "Delete ${last_release_version}" +``` + +### 4.在Apache Staging仓库发布版本 + +- 登录http://repository.apache.org , 使用Apache账号登录 +- 点击左侧的Staging repositories, +- 搜索EventMesh关键字,选择你最近上传的仓库,投票邮件中指定的仓库 +- 点击上方的`Release`按钮,这个过程会进行一系列检查 + +> 等仓库同步到其他数据源,一般需要24小时 + +### 5.GitHub版本发布 + +1.Tag the commit (on which the vote happened) with the release version without `-${RELEASE_CANDIDATE}`. 例如:after a successful vote on `v1.2-rc5`, the hash will be tagged again with `v1.2` only. + +2.在 [GitHub Releases](https://github.com/apache/incubator-eventmesh/releases) 页面的 `${release_version}` 版本上点击 `Edit` + +编辑版本号及版本说明,并点击 `Publish release` + +### 6.更新下载页面 + +等待并确认新的发布版本同步至 Apache 镜像后,更新如下页面: + +https://eventmesh.apache.org/download/ + +https://eventmesh.apache.org/zh/download/ + +GPG签名文件和哈希校验文件的下载连接应该使用这个前缀:`https://downloads.apache.org/incubator/eventmesh/` + +> 注意:项目下载链接应该使用 https://www.apache.org/dyn/closer.lua 而不是 closer.cgi 或者 mirrors.cgi + +### 7.邮件通知版本发布完成 + +> 请确保Apache Staging仓库已发布成功,一般是在该步骤的24小时后发布邮件 + +发邮件到 `dev@eventmesh.apache.org` 、 `announce@apache.org`和`general@incubator.apache.org` + +标题: + +``` +[ANNOUNCE] Apache EventMesh (incubating) ${release_version} available +``` + +正文: + +``` +Hi all, + +Apache EventMesh (incubating) Team is glad to announce the new release of Apache EventMesh (incubating) ${release_version}. + +Apache EventMesh (incubating) is a dynamic cloud-native eventing infrastructure used to decouple the application and backend middleware layer, which supports a wide range of use cases that encompass complex multi-cloud, widely distributed topologies using diverse technology stacks. + +Download Links: https://eventmesh.apache.org/projects/eventmesh/download/ + +Release Notes: https://eventmesh.apache.org/events/release-notes/v${release_version}/ + +Website: https://eventmesh.apache.org/ + +EventMesh Resources: +- Issue: https://github.com/apache/incubator-eventmesh/issues +- Mailing list: dev@eventmesh.apache.org + + + +Apache EventMesh (incubating) Team +``` + diff --git a/docs/en/contribute/02-write-unit-test.md b/docs/en/contribute/02-write-unit-test.md new file mode 100644 index 0000000000..0c48e46bc6 --- /dev/null +++ b/docs/en/contribute/02-write-unit-test.md @@ -0,0 +1,77 @@ +# Unit Test Requirement + +- Each unit test case should use assertions instead of `System.out` output or `if` statement +- Each unit test case shouldn't call other cases or depend on the order of execution. +- Each unit test case should be repeatable and not depend on the external environment because the test might be executed in the continuous integration. +- The scope of each unit test should be small enough to help locate the problem at the method level. + +## Location and Naming Rules + +- The unit test should be placed in `src/test/java`. +- The unit test configuration file should be placed in `src/test/resources`. For example: + - Class to be tested: `src/main/java/org/apache/eventmesh/common/protocol/http/body/BaseResponseBody.java` + - Unit test: `src/test/java/org/apache/eventmesh/common/protocol/http/body/BaseResponseBodyTest.java` + - Unit test configuration: `src/test/resources/configuration.properties` +- The package name of the unit test class should be identical to the class to be tested. +- The name of the unit test class should be `{class or interface to be tested}Test`. For example: + - Class to be tested: `EventMeshUtil` + - Unit test class: `EventMeshUtilTest` +- The name of each test case should be `test{method name}`. For example: + - Method to be tested: `addProp(String key, String val)` + - Unit test case: `testAddProp` + +## Assertion Usage + +### Common Assertion + +| Methods | Instructions | +| :-------------- | :-------------- | +| `assertEquals` | Determines whether two objects or primitive types are equal | +| `assertNotEquals` | Determines whether two objects or primitive types are not equal | +| `assertTrue` | Determines whether the given Boolean value is `true` | +| `assertFalse` | Determines whether the given Boolean value is `false` | +| `assertNull` | Determines whether the given object reference is `null` | +| `assertNotNull` | Determines whether the given object reference is not `null` | +| `assertAll` | When multiple decision logic are processed together if only one error is reported, the whole test will fail | + +### Example + +#### `assertEquals()` + +```java +configuration.init(); +Assert.assertEquals("value1", configuration.eventMeshEnv); +``` + +#### `assertTrue()` + +```java +BaseResponseHeader header = BaseResponseHeader.buildHeader("200"); +Assert.assertTrue(header.toMap().containsKey(ProtocolKey.REQUEST_CODE)); +``` + +#### `assertFalse()` + +```java +Class nacosRegistryServiceClass = NacosRegistryService.class; +Field initStatus = nacosRegistryServiceClass.getDeclaredField("INIT_STATUS"); +initStatus.setAccessible(true); +Object initStatusField = initStatus.get(nacosRegistryService); +Assert.assertFalse((Boolean.parseBoolean(initStatusField.toString()))); +``` + +#### `assertNull()` + +```java +DefaultFullHttpResponse response = httpCommand.httpResponse(); +Assert.assertNull(response); +``` + +#### `assertNotNull()` + +```java +Codec.Decoder cd = new Codec.Decoder(); +ArrayList result = new ArrayList<>(); +cd.decode(null, buf, result); +Assert.assertNotNull(result.get(0)); +``` diff --git a/docs/en/contribute/03-new-contributor-guidelines.md b/docs/en/contribute/03-new-contributor-guidelines.md new file mode 100644 index 0000000000..1099734c8d --- /dev/null +++ b/docs/en/contribute/03-new-contributor-guidelines.md @@ -0,0 +1,145 @@ + +# How to Contribution + +If you are a new contributor who wants to contribute to the eventmesh community, please read this document, which describes how to contribute to the community, and if you find any questions in the document, feel free to leave comments or suggestions. + +## Preparation + +### Development environment + +- You should have the JDK installed in your development environment. + +### Code Style + +Import [EventMesh CheckStyle](https://github.com/apache/incubator-eventmesh/blob/master/style/checkStyle.xml) file to your IDEA. + +For IDEA, you can import check style file by: +```shell + Editor -> Code Style -> Java -> Scheme -> Import Scheme -> CheckStyle Configuration +``` + +If you can't see CheckStyle Configuration section under Import Scheme, you can install CheckStyle-IDEA plugin first, and you will see it. + +You can also use `./gradlew check` to check the code style. +(Note: this command will check all file in project, when you submit a pr, the ci will only check the file has been changed in this pr). + +### Workflow + +Here are the workflow for contributors: + +1. Fork to your own + +2. Clone fork to local repository +```git +git clone git@github.com:yourgithub/incubator-eventmesh.git +``` + +3. Create a new branch and work on it +```git +git checkout -b fix_patch_xx +``` + +4. Keep your branch in sync +```git +git remote add upstream git@github.com:apache/incubator-eventmesh.git +git fetch upstream master:upstream_master +git rebase upstream_master +``` + +5. Commit your changes (make sure your commit message concise) + +6. Push your commits to your forked repository + +7. Create a pull request + +## Explanation + +The original warehouse: https://github.com/apache/incubator-eventmesh The apache warehouse of eventmesh is called the original warehouse in the text. + +The Fork library: From https://github.com/apache/eventmesh fork to your own personal repository to become a fork library. + +So fork the original EventMesh repository into your own repository. + +## Development branch + +**The current development branch of eventmesh is Master. Please submit PR to this branch.** + +- We recommend that you create a new branch in your repository for development and submit the branch to the master branch of eventmesh. + +## Contribution Categories + +### Bug feedback or bug fixes + +- Whether it's a bug feedback or a fix, an issue needs to be created first to describe the bug in detail, so that the community can easily find and view the problem and code through the issue record. bug feedback issues usually need to contain a complete description of the bug information and reproducible scenarios. + +### Implementation of functions, refactoring + +- If you plan to implement a new feature (or refactoring), be sure to communicate with the eventmesh core development team via an Issue or other means, and describe the new feature (or refactoring), mechanism and scenario in detail during the communication process. + +### Documentation Improvement + +- You can find the eventmesh documentation at [eventmesh-docs](https://github.com/apache/incubator-eventmesh/tree/master/docs), and the documentation is supplemented or improved in a way that is also essential for eventmesh. + +## Contribution method + +There are two ways for new contributors to contribute to the eventmesh community: + +- If you find a bug in the eventmesh code that you want to fix, or if you provide a new feature for the eventmesh, submit an issue in the eventmesh and submit a pr to the eventmesh. + +- Other contributors in the eventmesh community have raised issues, the [`issue for first-time contributors`](https://github.com/apache/incubator-eventmesh/issues/888) sorted out by the community here are relatively simple PR, which can help you familiarize yourself with the process of making contributions to the eventmesh community. + +## Submit issue guidelines + +- If you don't know how to raise an issue on eventmesh, please read [about the issue](https://docs.github.com/cn/issues/tracking-your-work-with-issues/quickstart). + +- In the eventmesh community, there are issue templates that can be used for reference, if the type matches please use the template, if the issue template does not meet your requirements, you can open an empty issue template, for the issue please bring its matching feature labels. + +- For the name of the issue, please briefly describe your question or purpose in one sentence, and write in English for better global communication. + +## pull request (pr) submission guidelines + +- If you don't know how to initiate a pr for eventmesh, please see [about pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request). + +- Whether it's a bug fix, or a new feature development (if this pr is a new feature development, then documentation updates about the new feature should be included in this pr), please submit a PR to the current development branch master. + +- The pr submission should follow the template provided by eventmesh as well as the need to write the submission information, a brief description of what the pr you are submitting does is sufficient, please see the [template for details](https://github.com/apache/incubator-eventmesh/blob/master/.github/PULL_REQUEST_TEMPLATE.md). + +- The pr you submit needs to be associated with the issue you are fixing, or the issue you are raising,so your PR title should start with [ISSUE #xx]. + +- If your change is about a typo or small optimize, you needn't create an Issue, just submit a PR and title with [MINOR]. + +**Note:** + + - A single pull request should not be too large. If heavy changes are required, it's better to separate the changes to a few individual PRs. + + - After creating a PR, one or more committers will help to review the pull request, after approve, this PR will be merged in to eventmesh repository, and the related Issue will be closed. + +## review + +### PR review + +All code should be well reviewed by one or more committers. Some principles: + +- Readability: Important code should be well-documented. Comply with our [code style](https://github.com/apache/incubator-eventmesh/blob/master/style/checkStyle.xml). + +- Elegance: New functions, classes or components should be well-designed. + +- Testability: Important code should be well-tested (high unit test coverage). + +### License review + +EventMesh follows [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) policy. All source files should +have the Apache License header added to the file header. EventMesh uses the [apache/skywalking-eyes](https://github.com/apache/skywalking-eyes) to check +the source file header. + +### PR merge + +After a PR is approved by at least one committer, it can be merged. Before the merge, the committer can make changes to the commits message, requiring the commits +message to be clear without duplication, and use Squash and Merge to make sure one PR should only contain one commits. +For large multi-person PR, use Merge to merge, and fix the commits by rebase before merging. + +## Community + +### Contact us + +Mail: dev@eventmesh.apache.org \ No newline at end of file diff --git a/docs/en/contribute/_category_.json b/docs/en/contribute/_category_.json new file mode 100644 index 0000000000..56d36f918e --- /dev/null +++ b/docs/en/contribute/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 5, + "label": "Contribute", + "collapsed": false +} diff --git a/docs/en/design-document/01-workflow.md b/docs/en/design-document/01-workflow.md new file mode 100644 index 0000000000..fecae1ee66 --- /dev/null +++ b/docs/en/design-document/01-workflow.md @@ -0,0 +1,261 @@ +# EventMesh Workflow + +## Business Problem + +Imaging you are building a simple Order Management System for an E-Commerce Store. The system should be able to receive and provision new orders from a store website. The provisioning process should be able to process all orders, handle payments, as well as process shipments. + +For high availability and high performance, you architect the system using event-driven architecture (EDA), and build microservice apps to handle store frontend, order management, payment processing, and shipment management. You deploy the whole system in a cloud environment. To handle high workloads, you leverage a messaging system to buffer the loads, and scale up multiple instances of microservices. The architecture could look similar to: + +![Workflow Use Case](../../images/design-document/workflow-use-case.jpg) + +While each microservice is acting on its own event channels, EventMesh plays a crucial role of doing Event Orchestration. + +We use [CNCF Serverless Workflow](https://serverlessworkflow.io/) to describe this Event Workflow Orchestration. + +## CNCF Serverless Workflow + +CNCF Serverless Workflow defines a vendor-neutral, open-source, and fully community-driven ecosystem for defining and running DSL-based workflows that target the Serverless technology domain. + +Serverless Workflow defines a Domain Specific Language (DSL) to describe stateful and stateless workflow-based orchestrations of serverless functions and microservices. + +More details could be found in its [official github site](https://github.com/serverlessworkflow/specification) + +## EventMesh Workflow + +We leverage Serverless Workflow DSL to describe the EventMesh workflow. Based on its spec, the workflow is consists of a series of workflow states used to describe the control-flow logic. At this time we only support event related workflow states. See the supported states in [Workflow DSL Design](#workflow-dsl-design-wip). + +A `workflow state` can include applicable `actions`, or services/functions that should be invoked during workflow execution. These `actions` can reference reusable `function` definitions which define how these functions/services should be invoked. They can also reference events that trigger event-based service invocations, and events to wait for that denote completion of such event-based service invocation completion. + +In EDA solution, we usually defined our event-driven microservice using AsyncAPI. Serverless workflow `function` definitions support defining invocation semantics using AsyncAPI. See [Using Funtions for AsyncAPI Service](https://github.com/serverlessworkflow/specification/blob/main/specification.md#using-functions-for-async-api-service-invocations) for more information. + +### AsyncAPI + +AsyncAPI is an open source initiative that seeks to improve the current state of Event-Driven Architectures (EDA). +Our long-term goal is to make working with EDAs as easy as it is to work with REST APIs. +That goes from documentation to code generation, discovery to event management. +Most of the processes you apply to your REST APIs nowadays would be applicable to your event-driven/asynchronous APIs too. + +See AsyncAPI detail in the [official site](https://www.asyncapi.com/docs/getting-started) + +### Workflow Example + +In this example, we build the event-driven workflow of the Order management system above. + +First, we need to define AsyncAPI definitions for our microservice apps. + +- Online Store App + +```yaml +asyncapi: 2.2.0 +info: + title: Online Store application + version: '0.1.0' +channels: + store/order: + subscribe: + operationId: newStoreOrder + message: + $ref : '#/components/NewOrder' + +``` + +- Order Service + +```yaml +asyncapi: 2.2.0 +info: + title: Order Service + version: '0.1.0' +channels: + order/inbound: + publish: + operationId: sendOrder + message: + $ref : '#/components/Order' + order/outbound: + subscribe: + operationId: processedOrder + message: + $ref : '#/components/Order' +``` + +- Payment Service + +```yaml +asyncapi: 2.2.0 +info: + title: Payment Service + version: '0.1.0' +channels: + payment/inbound: + publish: + operationId: sendPayment + message: + $ref : '#/components/OrderPayment' + payment/outbound: + subscribe: + operationId: paymentReceipt + message: + $ref : '#/components/OrderPayment' +``` + +- Shipment Service + +```yaml +asyncapi: 2.2.0 +info: + title: Shipment Service + version: '0.1.0' +channels: + shipment/inbound: + publish: + operationId: sendShipment + message: + $ref : '#/components/OrderShipment' +``` + +Once that is defined, we define the order workflow that describes our Order Management business logic. + +```yaml +id: storeorderworkflow +version: '1.0' +specVersion: '0.8' +name: Store Order Management Workflow +states: + - name: Receive New Order Event + type: event + onEvents: + - eventRefs: + - NewOrderEvent + actions: + - eventRef: + triggerEventRef: OrderServiceSendEvent + resultEventRef: OrderServiceResultEvent + - eventRef: + triggerEventRef: PaymentServiceSendEvent + resultEventRef: PaymentServiceResultEvent + transition: Check Payment Status + - name: Check Payment Status + type: switch + dataConditions: + - name: Payment Successfull + condition: "${ .payment.status == 'success' }" + transition: Send Order Shipment + - name: Payment Denied + condition: "${ .payment.status == 'denied' }" + end: true + defaultCondition: + end: true + - name: Send Order Shipment + type: operation + actions: + - eventRef: + triggerEventRef: ShipmentServiceSendEvent + end: true +events: + - name: NewOrderEvent + source: file://onlineStoreApp.yaml#newStoreOrder + type: asyncapi + kind: consumed + - name: OrderServiceSendEvent + source: file://orderService.yaml#sendOrder + type: asyncapi + kind: produced + - name: OrderServiceResultEvent + source: file://orderService.yaml#processedOrder + type: asyncapi + kind: consumed + - name: PaymentServiceSendEvent + source: file://paymentService.yaml#sendPayment + type: asyncapi + kind: produced + - name: PaymentServiceResultEvent + source: file://paymentService.yaml#paymentReceipt + type: asyncapi + kind: consumed + - name: ShipmentServiceSendEvent + source: file://shipmentService.yaml#sendShipment + type: asyncapi + kind: produced +``` + +The corresponding workflow diagram is the following: + +![Workflow Diagram](../../images/design-document/workflow-diagram.png) + +## EventMesh Workflow Engine + +In the following architecture diagram, the EventMesh Catalog, EventMesh Workflow Engine and EventMesh Runtime are running in three different processors. + +![Workflow Architecture](../../images/design-document/workflow-architecture.jpg) + +The steps running the workflow is the followings: + +1. Deploy the Publisher and Subscriber Apps in the environment. + Describe the App APIs using AsyncAPI, generate the asyncAPI yaml. + Register the Publisher and Subscriber Apps in EventMesh Catalog using AsyncAPI. + +2. Register the Serverless Workflow DSL in EventMesh Workflow Engine. + +3. EventMesh Workflow Engine query the EventMesh Catalog for Publisher and Subscribers required in Workflow DSL `function` + +4. Event-driven Apps are publish events to EventMesh Runtime to trigger the Workflow. EventMesh Workflow Engine also publish and subscribe events for orchestrating the events. + +### EventMesh Catalog Design + +EventMesh Catalog store the Publisher, Subscriber and Channel metadata. consists of the following modules: + +- AsyncAPI Parser + + Using the SDK provided by AsyncAPI community (see [tool list](https://www.asyncapi.com/docs/community/tooling)), + parse and validated the AsyncAPI yaml inputs, and generate the AsyncAPI definition. + +- Publisher, Channel, Subscriber Modules + + From the AsyncAPI definition store the Publisher, Subscriber and Channel information. + +### EventMesh Workflow Engine Design + +EventMesh Workflow Engine consists of the following modules: + +- Workflow Parser + + Using the SDK provided by Serverless Workflow community (see supported [SDKs](https://github.com/serverlessworkflow/specification#sdks)), + parse and validated the workflow DSL inputs, and generate workflow definition. + +- Workflow Module + + It manages a workflow instance life cycle, from create, start, stop to destroy. + +- State Module + + It manages workflow state life cycle. We support the event-related states, and the supported state list below is Work-in-Progress. + + | Workflow State | Description | + | --- | --- | + | Operation | Execute the AsyncAPI functions defined in the Actions | + | Event | Check if the defined Event matched, if so execute the defined AsyncAPI functions | + | Switch | Check the event is matched with the event-conditions, and execute teh defined AsyncAPI functions | + | Parallel | Execute the defined AsyncAPI functions in parallel | + | ForEach | Iterate the inputCollection and execute the defined AsyncAPI functions | + +- Action Module + + It managed the functions inside the action. + +- Function Module + + It manages the AsyncAPI functions by creating the publisher and/or subscriber in EventMesh Runtime, and manage the publisher/subscriber life cycle. + + | AsyncAPI Operation | EventMesh Runtime | + | --- | --- | + | Publish | Publisher | + | Subscribe | Subscriber | + +- Event Module + + It manages the CloudEvents data model, including event filter, correlation and transformation using the rules defined in the workflow DSL. + +- Retry Module + + It manages the retry logic of the event publishing into EventMesh Runtime. diff --git a/docs/en/design-document/02-runtime-protocol.md b/docs/en/design-document/02-runtime-protocol.md new file mode 100644 index 0000000000..b992bf896b --- /dev/null +++ b/docs/en/design-document/02-runtime-protocol.md @@ -0,0 +1,401 @@ +# EventMesh Runtime Protocol + +## TCP Protocol + +### Protocol Format + +|Name|Size|Description| +|-|-|-| +|Magic Code|9 bytes|Default: `EventMesh`| +|Protocol Version|4 bytes|Default: `0000`| +|Message Size|4 bytes|The total length of the message| +|Header Size|4 bytes|The length of the message header| +|Message Body||The content of the message| + +### Message Object in the Business Logic Layer + +#### Message Composition + +The `Package` class in the [`Package.java` file](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Package.java) is the TCP message object used in business logic layer. The class contains the `header` and `body` fields. + +```java +public class Package { + private Header header; + private Object body; +} + +public class Header { + private Command cmd; + private int code; + private String msg; + private String seq; +} +``` + +#### Specification + +- Message Header (the `header` field): The `cmd` field in the `Header` class specifies the different types of messages. +- Message Body (the `body` field): The type of the message body should be defined based on `cmd` field in the `Header` class. + +|Command|Type of Body| +|-|-| +| HEARTBEAT_REQUEST, HEARTBEAT_RESPONSE, HELLO_RESPONSE, CLIENT_GOODBYE_REQUEST, CLIENT_GOODBYE_RESPONSE, SERVER_GOODBYE_REQUEST, SERVER_GOODBYE_RESPONSE, LISTEN_REQUEST, LISTEN_RESPONSE, UNSUBSCRIBE_REQUEST, SUBSCRIBE_RESPONSE, UNSUBSCRIBE_RESPONSE, ASYNC_MESSAGE_TO_SERVER_ACK, BROADCAST_MESSAGE_TO_SERVER_ACK|N/A| +|HELLO_REQUEST|UserAgent| +|SUBSCRIBE_REQUEST|Subscription| +| REQUEST_TO_SERVER, REQUEST_TO_CLIENT, RESPONSE_TO_SERVER, RESPONSE_TO_CLIENT, ASYNC_MESSAGE_TO_SERVER, ASYNC_MESSAGE_TO_CLIENT, BROADCAST_MESSAGE_TO_SERVER, BROADCAST_MESSAGE_TO_CLIENT, ASYNC_MESSAGE_TO_CLIENT_ACK, BROADCAST_MESSAGE_TO_CLIENT_ACK, RESPONSE_TO_CLIENT_ACK, REQUEST_TO_CLIENT_ACK|OpenMessage| +|REDIRECT_TO_CLIENT|RedirectInfo| + +### Example of Client-Server Interaction + +```java +public enum Command { + // Heartbeat + HEARTBEAT_REQUEST(0), // Client send heartbeat request to server + HEARTBEAT_RESPONSE(1), // Server reply heartbeat response to client + + // Hello + HELLO_REQUEST(2), // Client send connect request to server + HELLO_RESPONSE(3), // Server reply connect response to client + + // Disconncet + CLIENT_GOODBYE_REQUEST(4), // Client send disconnect request to server + CLIENT_GOODBYE_RESPONSE(5), // Server reply disconnect response to client + SERVER_GOODBYE_REQUEST(6), // Server send disconncet request to client + SERVER_GOODBYE_RESPONSE(7), // Client reply disconnect response to server + + // Subscribe and UnSubscribe + SUBSCRIBE_REQUEST(8), // Slient send subscribe request to server + SUBSCRIBE_RESPONSE(9), // Server reply subscribe response to client + UNSUBSCRIBE_REQUEST(10), // Client send unsubscribe request to server + UNSUBSCRIBE_RESPONSE(11), // Server reply unsubscribe response to client + + // Listen + LISTEN_REQUEST(12), // Client send listen request to server + LISTEN_RESPONSE(13), // Server reply listen response to client + + // Send sync message + REQUEST_TO_SERVER(14), // Client (Producer) send sync message to server + REQUEST_TO_CLIENT(15), // Server push sync message to client(Consumer) + REQUEST_TO_CLIENT_ACK(16), // Client (Consumer) send ack of sync message to server + RESPONSE_TO_SERVER(17), // Client (Consumer) send reply message to server + RESPONSE_TO_CLIENT(18), // Server push reply message to client(Producer) + RESPONSE_TO_CLIENT_ACK(19), // Client (Producer) send acknowledgement of reply message to server + + // Send async message + ASYNC_MESSAGE_TO_SERVER(20), // Client send async msg to server + ASYNC_MESSAGE_TO_SERVER_ACK(21), // Server reply ack of async msg to client + ASYNC_MESSAGE_TO_CLIENT(22), // Server push async msg to client + ASYNC_MESSAGE_TO_CLIENT_ACK(23), // Client reply ack of async msg to server + + // Send broadcast message + BROADCAST_MESSAGE_TO_SERVER(24), // Client send broadcast msg to server + BROADCAST_MESSAGE_TO_SERVER_ACK(25), // Server reply ack of broadcast msg to client + BROADCAST_MESSAGE_TO_CLIENT(26), // Server push broadcast msg to client + BROADCAST_MESSAGE_TO_CLIENT_ACK(27), // Client reply ack of broadcast msg to server + + // Redirect + REDIRECT_TO_CLIENT(30), // Server send redirect instruction to client +} +``` + +### Client-Initiated Interaction + +|Scene|Client Request|Server Response| +|-|-|-| +| Hello | HELLO_REQUEST | HELLO_RESPONSE | | +| Heartbeat | HEARTBEAT_REQUEST | HEARTBEAT_RESPONSE | | +| Subscribe | SUBSCRIBE_REQUEST | SUBSCRIBE_RESPONSE | | +| Unsubscribe | UNSUBSCRIBE_REQUEST | UNSUBSCRIBE_RESPONSE | | +| Listen | LISTEN_REQUEST | LISTEN_RESPONSE | | +| Send sync message | REQUEST_TO_SERVER | RESPONSE_TO_CLIENT | | +| Send the response of sync message| RESPONSE_TO_SERVER | N/A | | +| Send async message | ASYNC_MESSAGE_TO_SERVER | ASYNC_MESSAGE_TO_SERVER_ACK | | +| Send broadcast message | BROADCAST_MESSAGE_TO_SERVER | BROADCAST_MESSAGE_TO_SERVER_ACK | | +| Client start to disconnect | CLIENT_GOODBYE_REQUEST | CLIENT_GOODBYE_RESPONSE | | + +### Server-Initiated Interaction + +|Scene|Server Request|Client Response|Remark| +|-|-| ------------------------------- | ---- | +| Push sync message to client | REQUEST_TO_CLIENT | REQUEST_TO_CLIENT_ACK | | +| Push the response message of sync message to client | RESPONSE_TO_CLIENT | RESPONSE_TO_CLIENT_ACK | | +| Push async message to client | ASYNC_MESSAGE_TO_CLIENT | ASYNC_MESSAGE_TO_CLIENT_ACK | | +| Push broadcast message to client | BROADCAST_MESSAGE_TO_CLIENT | BROADCAST_MESSAGE_TO_CLIENT_ACK | | +| Server start to disconnect | SERVER_GOODBYE_REQUEST | -- | | +| Server send redirect | REDIRECT_TO_CLIENT | -- | | + +### Type of Message + +#### Sync Message + +![Sync Message](../../images/design-document/sync-message.png) + +#### Async Message + +![Async Message](../../images/design-document/async-message.png) + +#### Boardcast Message + +![Boardcast Message](../../images/design-document/broadcast-message.png) + +## HTTP Protocol + +### Protocol Format + +The `EventMeshMessage` class in the [`EventMeshMessage.java` file](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-common/src/main/java/org/apache/eventmesh/common/EventMeshMessage.java) is the HTTP message definition of EventMesh Runtime. + +```java +public class EventMeshMessage { + private String bizSeqNo; + + private String uniqueId; + + private String topic; + + private String content; + + private Map prop; + + private final long createTime = System.currentTimeMillis(); +} +``` + +### HTTP Post Request + +#### Heartbeat Message + +##### Request Header + +| Key | Description | +| -------- | ---------------- | +| Env | Enviroment of Client | +| Region | Region of Client | +| Idc | IDC of Client | +| Dcn | DCN of Client | +| Sys | Subsystem ID of Client | +| Pid | Client Process ID | +| Ip | Client Ip | +| Username | Client username | +| Passwd | Client password | +| Version | Protocol version | +| Language | Develop language | +| Code | Request Code | + +##### Request Body + +|Key|Description| +|-|-| +|`clientType`|`ClientType.PUB` for Producer, `ClientType.SUB` for Consumer| +|`heartbeatEntities`|Topic, URL, etc.| + +#### Subscribe Message + +##### Request Header + +The request header of the Subscribe message is identical to the request header of the Heartbeat message. + +##### Request Body + +|Key|Description| +|-|-| +|`topic`|The topic that the client requested to subscribe to| +|`url`|The callback URL of the client| + +#### Unsubscribe Message + +##### Request Header + +The request header of the Unsubscribe message is identical to the request header of the Heartbeat message. + +##### Request Body + +The request body of the Unsubscribe message is identical to the request body of the Subscribe message. + +#### Send Async Message + +##### Request Header + +The request header of the Send Async message is identical to the request header of the Heartbeat message. + +##### Request Body + +|Key|Description| +|-|-| +|`topic`|Topic of the message| +|`content`|The content of the message| +|`ttl`|The time-to-live of the message| +|`bizSeqNo`|The biz sequence number of the message| +|`uniqueId`|The unique ID of the message| + +### Client-Initiated Interaction + +|Scene|Client Request|Server Response|Remark| +|-|-|-|-| +| Heartbeat | HEARTBEAT(203) | SUCCESS(0) or EVENTMESH_HEARTBEAT_ERROR(19) | | +| Subscribe | SUBSCRIBE(206) | SUCCESS(0) or EVENTMESH_SUBSCRIBE_ERROR(17) | | +| Unsubscribe | UNSUBSCRIBE(207) | SUCCESS(0) or EVENTMESH_UNSUBSCRIBE_ERROR(18) | | +| Send async message | MSG_SEND_ASYNC(104) | SUCCESS(0) or EVENTMESH_SEND_ASYNC_MSG_ERR(14) | | + +### Server-Initiated Interaction + +|Scene|Client Request|Server Response|Remark| +|-|-|-|-| +|Push async message to the client|HTTP_PUSH_CLIENT_ASYNC(105)|`retCode`|The push is successful if the `retCode` is `0`| + +## gRPC Protocol + +### Protobuf + +The `eventmesh-protocol-gprc` module contains the [protobuf definition file](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-protocol-plugin/eventmesh-protocol-grpc/src/main/proto/eventmesh-client.proto) of the Eventmesh client. The `gradle build` command generates the gRPC codes, which are located in `/build/generated/source/proto/main`. The generated gRPC codes are used in `eventmesh-sdk-java` module. + +### Data Model + +#### Message + +The message data model used by `publish()`, `requestReply()` and `broadcast()` APIs is defined as: + +```protobuf +message RequestHeader { + string env = 1; + string region = 2; + string idc = 3; + string ip = 4; + string pid = 5; + string sys = 6; + string username = 7; + string password = 8; + string language = 9; + string protocolType = 10; + string protocolVersion = 11; + string protocolDesc = 12; +} + +message SimpleMessage { + RequestHeader header = 1; + string producerGroup = 2; + string topic = 3; + string content = 4; + string ttl = 5; + string uniqueId = 6; + string seqNum = 7; + string tag = 8; + map properties = 9; +} + +message BatchMessage { + RequestHeader header = 1; + string producerGroup = 2; + string topic = 3; + + message MessageItem { + string content = 1; + string ttl = 2; + string uniqueId = 3; + string seqNum = 4; + string tag = 5; + map properties = 6; + } + + repeated MessageItem messageItem = 4; +} + +message Response { + string respCode = 1; + string respMsg = 2; + string respTime = 3; +} +``` + +#### Subscription + +The subscription data model used by `subscribe()` and `unsubscribe()` APIs is defined as: + +```protobuf +message Subscription { + RequestHeader header = 1; + string consumerGroup = 2; + + message SubscriptionItem { + enum SubscriptionMode { + CLUSTERING = 0; + BROADCASTING = 1; + } + + enum SubscriptionType { + ASYNC = 0; + SYNC = 1; + } + + string topic = 1; + SubscriptionMode mode = 2; + SubscriptionType type = 3; + } + + repeated SubscriptionItem subscriptionItems = 3; + string url = 4; +} +``` + +#### Heartbeat + +The heartbeat data model used by the `heartbeat()` API is defined as: + +```protobuf +message Heartbeat { + enum ClientType { + PUB = 0; + SUB = 1; + } + + RequestHeader header = 1; + ClientType clientType = 2; + string producerGroup = 3; + string consumerGroup = 4; + + message HeartbeatItem { + string topic = 1; + string url = 2; + } + + repeated HeartbeatItem heartbeatItems = 5; +} +``` + +### Service Definition + +#### Event Publisher Service + +```protobuf +service PublisherService { + // Async event publish + rpc publish(SimpleMessage) returns (Response); + + // Sync event publish + rpc requestReply(SimpleMessage) returns (Response); + + // Batch event publish + rpc batchPublish(BatchMessage) returns (Response); +} +``` + +#### Event Consumer Service + +```protobuf +service ConsumerService { + // The subscribed event will be delivered by invoking the webhook url in the Subscription + rpc subscribe(Subscription) returns (Response); + + // The subscribed event will be delivered through stream of Message + rpc subscribeStream(Subscription) returns (stream SimpleMessage); + + rpc unsubscribe(Subscription) returns (Response); +} +``` + +#### Client Hearthbeat Service + +```protobuf +service HeartbeatService { + rpc heartbeat(Heartbeat) returns (Response); +} +``` diff --git a/docs/en/design-document/03-stream.md b/docs/en/design-document/03-stream.md new file mode 100644 index 0000000000..d379ccddd2 --- /dev/null +++ b/docs/en/design-document/03-stream.md @@ -0,0 +1,118 @@ +# EventMesh Stream + +## Overview of Event Streaming + +Event Streaming is an implementation of Pub/Sub architecture pattern,it consist of + +- Message or Event: Change of State. + +- Topic: Partition in messaging middle ware broker. + +- Consumer: Can subscribe to read events from broker topic. + +- Producer: Generate events + +Streaming of event is continuous flow of events in order to maintain order between events, events flow should be in a specific direction means from producers to consumers. + +## Requirements + +### Functional Requirements + +| Requirement ID | Requirement Description | Comments | +| -------------- | ----------------------- | -------- | +| F-1 | EventMesh users should be able to achieve Event Streaming functionality in EventMesh | Functionality | +| F-2 | EventMesh users can apply dynamic user specific logics for routing, filter, transformation etc | Functionality | + +## Design Details + +We are introduce EventMesh Stream component allow us to use programming model and binder abstractions +from Spring Cloud Stream natively within Apache Camel. + +[Spring-Cloud-Stream](https://spring.io/projects/spring-cloud-stream) Spring Cloud Stream is a framework for building +highly scalable event-driven microservices connected with shared messaging systems. + +[Apache Camel](https://camel.apache.org/) Camel is an Open Source integration framework that empowers you to quickly +and easily integrate various systems consuming or producing data. + +## Architecture + +![Stream Architecture](../../images/design-document/stream-architecture.png) + +## Design + +### EventMesh-Stream Component + +- Event +- Event Channel +- Event EndPoint +- Event Pipes & Filters +- Event Routes +- Event Converter + +#### Event + +> A event is the smallest unit for transmitting data in system. It structure divided into headers, body and attachments. + +#### Event Channel + +> A event channel is a logical channel in system, we are achieving by Spring Cloud Stream programming model, it has abstract functionality around messaging channels(As of now Spring `MessageChannel`). + +#### Event EndPoint + +> A event endpoint is the interface between an application and a messaging system. We can define two types of endpoint + +- Consumer endpoint - Appears at start of a route and read incoming events from an incoming channel. +- Producer endpoint - Appears at end of a route and write incoming events to an outgoing channel. + +#### Event Pipes & Filters + +> We can construct a route by creating chain of filters( Apache Camel `Processor`), where the output of one filter is fed into input for next filter in the pipeline. +The main advantage of the pipeline is that you can create complex event processing logic. + +#### Event Routes + +> A event router, is a type of filter on consumer and redirect them to the appropriate target endpoint based on a decision criteria. + +#### Event Converter + +> The event converter that modifies the contents of a event, translating it to a different format(i.e cloudevents -> Event (Camel) -> Binder Message(Spring Message) and vice versa). + +## EventMesh-Stream Component Interfaces + +### Component + +Component interface is the primary entry point, you can use Component object as a factory to create EndPoint objects. + +![Stream Component Interface](../../images/design-document/stream-component-interface.png) + +### EndPoint + +EndPoint which is act as factories for creating Consumer, Producer and Event objects. + +- `createConsumer()` — Creates a consumer endpoint, which represents the source endpoint at the beginning of a route. +- `createProducer()` — Creates a producer endpoint, which represents the target endpoint at the end of a route. + +![Stream Component Routes](../../images/design-document/stream-component-routes.png) + +#### Producer + +User can create following types of producer +> Synchronous Producer-Processing thread blocks until the producer has finished the event processing. + +![Stream Sync Producer](../../images/design-document/stream-sync-producer.png) + +In future Producer Types: + +- Asynchronous Producer - Producer process the event in a sub-thread. + +#### Consumer + +User can create following types of consumer +> Event-driven consumer-the processing of an incoming request is initiated when message binder call a method in consumer. + +![Stream Event-Driven Consumer](../../images/design-document/stream-event-driven-consumer.png) + +In the Future + +- Scheduled poll consumer +- Custom polling consumer diff --git a/docs/en/design-document/04-schema-registry.md b/docs/en/design-document/04-schema-registry.md new file mode 100644 index 0000000000..5c0b65f98e --- /dev/null +++ b/docs/en/design-document/04-schema-registry.md @@ -0,0 +1,134 @@ +# EventMesh Schema Registry (OpenSchema) + +## Overview of Schema and Schema Registry + +### Schema + +A Schema stands for the description of serialization instances(string/stream/file/...) and has two properties. First, it is also in the format of serialization type. Second, it defines what requirements such serialized instances should satisfy. + +Besides describing a serialization instance, a Schema may also be used for validating whether an instance is legitimate. The reason is that it defines the ```type```(and other properties) of a serialized instance and inside keys. Taking JSON Schema for example, it could not only be referred when describing a JSON string, but also be used for validating whether a string satisfies properties defined in the schema[[1]](#References). + +Commonly, there are JSON Schema, Protobuf Schema, and Avro Schema. + +### Schema Registry + +Schema Registry is a server provides RESTful interfaces. It could receive and store Schemas from clients, as well as provide intrefaces for other clients to retrieve Schemas from it. + +It could be applied to validation process and (de-)serialization process. + +### Comparison of Schema Registry in Different Projects + +Project | Application +:---: | :--- +EMQ[[2]](#References) | Mainly in (de-)serialization process. Use "Schema Registry" and "Rule Matching" to transfer a message from one serialization format to another. +Pulsar[[3]](#References) | Mainly in validation process. Use "Schema Registry" to validate a message. +Confluentinc[[4]](#References) | In both validation and (de-)serialization process. + +## Overview of OpenSchema + +OpenSchema[[5]](#References) proposes a specification for data schema when exchanging the message and event in more and more modern cloud-native applications. It designs a RESTful interface for storing and retrieving such as Avro, JSON Schema, and Protobuf3 schemas from three aspects(subject/schema/compatibility). + +## Requirements(Goals) + +| Requirement ID | Requirement Description | Comments | +| :------------- | ------------------------------------------------------------ | ------------- | +| F-1 | In transmission, no message needs to contain schema information which bring efficiency. | Functionality | +| F-2 | The message content from producer could be validated whether serialized correctly according to schema. | Functionality | + +## Design Details + +### Architecture + +![OpenSchema](../../images/design-document/schema-registry-architecture.png) + +### Process of Transferring Messages under Schema Registry + +![Process](../../images/design-document/schema-registry-process.jpg) + +The highlevel process of messages transmission contains 10 steps as follows: + +- 1: Consumer subscribes "TOPIC" messages from EventMesh. +- 2: Producer registers a schema to EventMesh. +- 3: EventMesh registers a schema to Schema Registry. +- 4: Schema Registry returns the id of newly created schema; EventMesh caches such id and schema. +- 5: EventMesh returns the id of schema to Producer. +- 6: Producer patches the id in front of messages and send messages to EventMesh. +- 7: EventMesh validates the messages in the entry port and send it to EventStore; EventMesh retrieves messages from EventStore. +- 8: EventMesh unpatches the id and send it to Schema Registry(if such `` does not exists in local cache). +- 9: Schema Registry returns schema and EventMesh caches it. +- 10: EventMesh patches schema in front of messages and push it to consumer. + +## Current Progress + +### Status + +**Current state**: Developing + +**Discussion thread**: ISSUE #339 + +### Proposed Changes + +The proposal has two aspects. + +First is a separated Open Schema Registry, which includes storage and compatibility check for schema. +This proposal is under developing. + +Second is the integration of Open Schema in Eventmesh, which includes validation for schema. This proposal is to be developed. + +As for the first proposal, some developing statuses are as follows. + +#### Status Code and Exception Code + +No. | Status Code | Exception Code | Description | status +--- | :---: | :---: | :---: | :---: +1 | 401 | 40101 | Unauthorized Exception | ✔ +2 | 404 | 40401 | Schema Non- Exception | ✔ +3 | ^ | 40402 | Subject Non-exist Exception | ✔ +4 | ^ | 40403 | Version Non-exist Exception | ✔ +5 | 409 | 40901 | Compatibility Exception | ✔ +6 | 422 | 42201 | Schema Format Exception | ✔ +7 | ^ | 42202 | Subject Format Exception | ✔ +8 | ^ | 42203 | Version Format Exception | ✔ +9 | ^ | 42204 | Compatibility Format Exception | ✔ +10 | 500 | 50001 | Storage Service Exception | ✔ +11 | ^ | 50002 | Timeout Exception | ✔ + +#### API Development Status + +No. | Type | URL | response | exception | code | test +--- | --- | --- | --- | --- | --- | --- +1 | GET | /schemas/ids/{string: id} | `Schema.class` | 40101\40401\50001 | ✔ | ❌ +2 | GET | /schemas/ids/{string: id}/subjects | `SubjectAndVersion.class` | 40101\40401\50001 | ✔ | ❌ +3 | GET | /subjects | `List\` | 40101\50001 | ✔ | ❌ +4 | GET | /subjects/{string: subject}/versions | `List\` | 40101\40402\50001 | ✔ | ❌ +5 | DELETE | /subjects/(string: subject) | `List\` | 40101\40402\50001 | ✔ | ❌ +6 | GET | /subjects/(string: subject) | `Subject.class` | 40101\40402\50001 | ✔ | ❌ +7 | GET | /subjects/(string: subject)/versions/(version: version)/schema | `SubjectWithSchema.class` | 40101\40402\40403\50001 | ✔ | ❌ +8 | POST | /subjects/(string: subject)/versions | `SchemaIdResponse.class` | 40101\40901\42201\50001\50002 | - | ❌ +9 | POST | /subjects/(string: subject)/ | `Subject.class` | 40101\40901\42202\50001\50002 | ✔ | ❌ +10 | DELETE | /subjects/(string: subject)/versions/(version: version) | `int` | 40101\40402\40403\40901\50001| - | ❌ +11 | POST | /compatibility/subjects/(string: subject)/versions/(version: version) | `CompatibilityResultResponse.class` | 40101\40402\40403\42201\42203\50001| - | ❌ +12 | GET | /compatibility/(string: subject) | `Compatibility.class` | 40101\40402\50001 | ✔ | ❌ +13 | PUT | /compatibility/(string: subject) | `Compatibility.class` | 40101\40402\40901\42204\50001 | - | ❌ + +#### Overall Project Structure + +```SchemaController.java```+```SchemaService.java``` : ```OpenSchema 7.1.1~7.1.2 (API 1~2)``` + +```SubjectController.java```+```SubjectService.java``` : ```OpenSchema 7.2.1~7.2.8 (API 3~10)``` + +```CompatibilityController.java```+```CompatibilityService.java``` : ```OpenSchema 7.3.1~7.3.3 (API 11~13)``` + ```Check for Compatibility``` + +![Project Structure](../../images/design-document/schema-registry-project-structure.png) + +## References + +[1] [schema validator (github.com)](https://github.com/search?q=schema+validator) + +[2] [EMQ: Schema Registry](https://www.jianshu.com/p/33e0655c642b) + +[3] [Pulsar: Schema Registry](https://mp.weixin.qq.com/s/PaB66-Si00cX80py5ig5Mw) + +[4] [confluentinc/schema-registry](https://github.com/confluentinc/schema-registry) + +[5] [openmessaging/openschema](https://github.com/openmessaging/openschema) diff --git a/docs/en/design-document/05-metrics-export.md b/docs/en/design-document/05-metrics-export.md new file mode 100644 index 0000000000..bab18761e3 --- /dev/null +++ b/docs/en/design-document/05-metrics-export.md @@ -0,0 +1,47 @@ +# EventMesh Metrics (OpenTelemetry and Prometheus) + +## Introduction + +[EventMesh(incubating)](https://github.com/apache/incubator-eventmesh) is a dynamic cloud-native eventing infrastructure. + +## An overview of OpenTelemetry + +OpenTelemetry is a collection of tools, APIs, and SDKs. You can use it to instrument, generate, collect, and export telemetry data (metrics, logs, and traces) for analysis in order to understand your software's performance and behavior. + +## An overview of Prometheus + +Power your metrics and alerting with a leading open-source monitoring solution. + +- Dimensional data +- Powerful queries +- Great visualization +- Efficient storage +- Simple operation +- Precise alerting +- Many client libraries +- Many integrations + +## Requirements + +### Functional Requirements + +| Requirement ID | Requirement Description | Comments | +| :------------- | ------------------------------------------------------------ | ------------- | +| F-1 | EventMesh users should be able to observe HTTP metrics from Prometheus | Functionality | +| F-2 | EventMesh users should be able to observe TCP metrics from Prometheus | Functionality | + +## Design Details + +use the meter instrument provided by OpenTelemetry to observe the metrics exist in EventMesh then export to Prometheus. + +1、Initialize a meter instrument + +2、set the Prometheus server + +3、different metrics observer built + +## Appendix + +### References + + diff --git a/docs/en/design-document/06-cloudevents.md b/docs/en/design-document/06-cloudevents.md new file mode 100644 index 0000000000..20a99d182a --- /dev/null +++ b/docs/en/design-document/06-cloudevents.md @@ -0,0 +1,106 @@ +# CloudEvents Integration + +## Introduction + +[CloudEvents](https://github.com/cloudevents/spec) is a specification for describing event data in common formats to provide interoperability across services, platforms and systems. + +As of May 2021, EventMesh contains the following major components: `eventmesh-runtime`, `eventmesh-sdk-java` and `eventmesh-connector-rocketmq`. +For a customer to use EventMesh, `eventmesh-runtime` can be deployed as microservices to transmit +customer's events between event producers and consumers. Customer's applications can then interact +with `eventmesh-runtime` using `eventmesh-sdk-java` to publish/subscribe for events on given topics. + +CloudEvents support has been a highly desired feature by EventMesh users. There are many reasons +for users to prefer using a SDK with CloudEvents support: + +- CloudEvents is a more widely accepted and supported way to describe events. `eventmesh-sdk-java` + currently uses the `LiteMessage` structure to describe events, which is less standardized. +- CloudEvents's Java SDK has a wider range of distribution methods. For example, EventMesh users + currently need to use the SDK tarball or build from source for every EventMesh release. With + CloudEvents support, it's easier for users to take a dependency on EventMesh's SDK using CloudEvents's public distributions (e.g. through a Maven configuration). +- CloudEvents's SDK supports multiple languages. Although EventMesh currently only supports a Java SDK, in future if more languages need to be supported, the extensions can be easier with experience on binding Java SDK with CloudEvents. + +## Requirements + +### Functional Requirements + +| Requirement ID | Requirement Description | Comments | +| -------------- | ----------------------- | -------- | +| F-1 | EventMesh users should be able to depend on a public SDK to publish/subscribe events in CloudEvents format | Functionality | +| F-2 | EventMesh users should continue to have access to existing EventMesh client features (e.g. load balancing) with an SDK that supports CloudEvent | Feature Parity | +| F-3 | EventMesh developers should be able to sync `eventmesh-sdk-java` and an SDK with CloudEvents support without much effort/pain | Maintainability | +| F-4 | EventMesh support pluggable protocols for developers integrate other protocols (e.g. CloudEvents\EventMesh Message\OpenMessage\MQTT ...) | Functionality | +| F-5 | EventMesh support the unified api for publish/subscribe events to/from event store | Functionality | + +### Performance Requirements + +| Requirement ID | Requirement Description | Comments | +| -------------- | ----------------------- | -------- | +| P-1 | Client side latency for SDK with CloudEvents support should be similar to current SDK | | + +## Design Details + +Binding with the CloudEvents Java SDK (similar to what Kafka already did, see Reference for more details) +should be an easy way to achieve the requirements. + +### Pluggable Protocols + +![Pluggable Protocols](../../images/design-document/cloudevents-pluggable-protocols.png) + +### Process of CloudEvents under EventMesh + +#### For TCP + +##### SDK side for publish + +- add the CloudEvents identifier in `package` header +- use `CloudEventBuilder` build the CloudEvent and put it into the `package` body + +##### SDK side for subscribe + +- add `convert` function under the `ReceiveMsgHook` interface, for converting the `package` body to the specific protocol with the identifier in `package` header +- different protocols should implement the `ReceiveMsgHook` interface + +##### Server side for publish + +- design the protocol convert api contains `decodeMessage` interface which convert the package's body to CloudEvent +- update `Session.upstreamMsg()` in `MessageTransferTask` change the input parameter Message to CloudEvent, the CloudEvent use the last step `decodeMessage` api convert +- update `SessionSender.send()` change the input parameter `Message` to `CloudEvent` +- update `MeshMQProducer` api support send `CloudEvents` in runtime +- support the implementation in `connector-plugin` for send `CloudEvents` to EventStore + +##### Server side for subscribe + +- support change the `RocketMessage` to `CloudEvent` in connector-plugin + +- overwrite the `AsyncMessageListener.consume()` function, change the input parameter `Message` to `CloudEvent` + +- update the `MeshMQPushConsumer.updateOffset()` implementation change the the input parameter `Message` to `CloudEvent` + +- update `DownStreamMsgContext` , change the input parameter `Message` to `CloudEvent`, update the `DownStreamMsgContext.ackMsg` + +#### For HTTP + +##### SDK side for publish + +- support `LiteProducer.publish(cloudEvent)` +- add the CloudEvents identifier in http request header + +##### SDK side for subscribe + +##### Server side for publish + +- support build the `HttpCommand.body` by pluggable protocol plugins according the protocol type in `HttpCommand` header +- support publish the CloudEvent in message processors + +##### Server side for subscribe + +- update the `EventMeshConsumer.subscribe()` + +- update `HandleMsgContext` , change the input parameter `Message` to `CloudEvent` +- update `AsyncHttpPushRequest.tryHTTPRequest()` + +## Appendix + +### References + +- diff --git a/docs/en/design-document/07-tracing.md b/docs/en/design-document/07-tracing.md new file mode 100644 index 0000000000..1b191965da --- /dev/null +++ b/docs/en/design-document/07-tracing.md @@ -0,0 +1,87 @@ +# Distributed Tracing + +## Overview of OpenTelemetry + +OpenTelemetry is a collection of tools, APIs, and SDKs. You can use it to instrument, generate, collect, and export telemetry data (metrics, logs, and traces) for analysis in order to understand your software's performance and behavior. + +## Requirements + +- set tracer +- different exporter +- start and end span in server + +## Design Details + +- SpanProcessor: BatchSpanProcessor + +- Exporter: log(default), would be changed from properties + +```java +// Configure the batch spans processor. This span processor exports span in batches. +BatchSpanProcessor batchSpansProcessor = + BatchSpanProcessor.builder(exporter) + .setMaxExportBatchSize(512) // set the maximum batch size to use + .setMaxQueueSize(2048) // set the queue size. This must be >= the export batch size + .setExporterTimeout( + 30, TimeUnit.SECONDS) // set the max amount of time an export can run before getting + // interrupted + .setScheduleDelay(5, TimeUnit.SECONDS) // set time between two different exports + .build(); +OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder().addSpanProcessor(batchSpansProcessor).build()) + .build(); +``` + +1. When using the method 'init()' of the class "EventMeshHTTPServer", the class "AbstractHTTPServer” will get the tracer + +```java +super.openTelemetryTraceFactory = new OpenTelemetryTraceFactory(eventMeshHttpConfiguration); +super.tracer = openTelemetryTraceFactory.getTracer(this.getClass().toString()); +super.textMapPropagator = openTelemetryTraceFactory.getTextMapPropagator(); +``` + +2. then the trace in class "AbstractHTTPServer” will work. + +## Problems + +### How to set different exporter in class 'OpenTelemetryTraceFactory'? (Solved) + +After I get the exporter type from properties, how to deal with it. + +The 'logExporter' only needs to new it. + +But the 'zipkinExporter' needs to new and use the "getZipkinExporter()" method. + +## Solutions + +### Solution of different exporter + +Use reflection to get an exporter. + +First of all, different exporter must implement the interface 'EventMeshExporter'. + +Then we get the exporter name from the configuration and reflect to the class. + +```java +//different spanExporter +String exporterName = configuration.eventMeshTraceExporterType; +//use reflection to get spanExporter +String className = String.format("org.apache.eventmesh.runtime.exporter.%sExporter",exporterName); +EventMeshExporter eventMeshExporter = (EventMeshExporter) Class.forName(className).newInstance(); +spanExporter = eventMeshExporter.getSpanExporter(configuration); +``` + +Additional, this will surround with try catch.If the specified exporter cannot be obtained successfully, the default exporter log will be used instead + +#### Improvement of different exporter + +SPI (To be completed) + +## Appendix + +### References + + + + diff --git a/docs/en/design-document/08-spi.md b/docs/en/design-document/08-spi.md new file mode 100644 index 0000000000..94da666e7f --- /dev/null +++ b/docs/en/design-document/08-spi.md @@ -0,0 +1,113 @@ +# Service Provider Interface + +## Introduction + +In order to improve scalability,EventMesh introduce the SPI(Service Provider Interface)mechanism, which can help to automatically find the concrete implementation +class of the extended interface at runtime and load it dynamically. In EventMesh, all extension modules are implemented by using plugin. +User can develop custom plugins by simply implementing extended interfaces, and select the plugin to be run at runtime by simply declare at configuration. + +## eventmesh-spi module + +The implementation of SPI is at eventmesh-spi module, there are three main classes `EventMeshSPI`, `EventMeshExtensionFactory` and `ExtensionClassLoader`. + +### EventMeshSPI + +EventMeshSPI is an SPI declaration annotation, all extended interface that want to be implemented should be declared by @EventMeshSPI. + +```java +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface EventMeshSPI { + /** + * If true, the spi instance is singleton + */ + boolean isSingleton() default false; +} +``` + +Use annotation to declare the interface is an SPI extended interface can improve the readability of the code. +On the other hand, @EventMeshSPI contains a isSingleton attribute which used to declare whether the extension instance is a singleton. +If this attribute is true, that means the instance of this interface will be singleton. + +### EventMeshExtensionFactory + +EventMeshExtensionFactory is a factory used to get the SPI extension instance which contains a static method `getExtension(Class extensionType, String extensionName)`. + +```java +public enum EventMeshExtensionFactory { + /** + * @param extensionType extension plugin class type + * @param extensionName extension instance name + * @param the type of the plugin + * @return plugin instance + */ + public static T getExtension(Class extensionType, String extensionName) { + /* ... */ + } +} +``` + +If you want to get the extension instance, you should use EventMeshExtensionFactory. + +### ExtensionClassLoader + +ExtensionClassLoader is used to load extension instance classed, it has two subclass MetaInfExtensionClassLoader and JarExtensionClassLoader. + +```java +/** + * Load extension class + *
    + *
  • {@link MetaInfExtensionClassLoader}
  • + *
  • {@link JarExtensionClassLoader}
  • + *
+ */ +public interface ExtensionClassLoader { + /** + * load + * + * @param extensionType extension type class + * @param extension type + * @return extension instance name to extension instance class + */ + Map> loadExtensionClass(Class extensionType); +} +``` + +MetaInfExtensionClassLoader used to load class from classPath, and JarExtensionClassLoader used to load class from extension jar on the plugin directory. +In the future, we might support the implementation to load from the maven repository. + +## SPI use case + +The following is an example of how to use the SPI to declare a plugin. + +First, we create an eventmesh-connector-api module, and define the extension interface MeshMQProducer, and we use @EventMeshSPI on the MeshMQProducer, +which indicates the MeshMQProducer is an SPI interface. + +```java +@EventMeshSPI(isSingleton = false) +public interface MeshMQProducer extends Producer { + /* ... */ +} +``` + +Then we create an eventmesh-connector-rocketmq module, which contains the concrete implementation named RocketMQProducerImpl. + +```java +public class RocketMQProducerImpl implements MeshMQProducer { + /* ... */ +} +``` + +At the same time, we need to create a file with the full qualified name of the SPI interface under the resource/META-INF/eventmesh directory +in the eventmesh-connector-rocketmq module. + +org.apache.eventmesh.api.producer.Producer + +The content of the file is the extension instance name and the corresponding instance full class name + +```properties +rocketmq=org.apache.eventmesh.connector.rocketmq.producer.RocketMQProducerImpl +``` + +At this point, an SPI expansion module is complete. We can use `EventMeshExtensionFactory.getExtension(MeshMQProducer.class, "rocketmq")` to get the `RocketMQProducerImpl` instance. diff --git a/docs/en/design-document/09-event-bridge.md b/docs/en/design-document/09-event-bridge.md new file mode 100644 index 0000000000..b74b78e015 --- /dev/null +++ b/docs/en/design-document/09-event-bridge.md @@ -0,0 +1,156 @@ +# Event Bridge + +![event-bridge](../../images/eventmesh-bridge.png) + +Event Bridge 可以支持跨mesh集群的消息投递,下面展示这一功能的详细设计与体验步骤 + +![event-bridge-detail](../../images/design-document/event-bridge-detail.png) + +> 注:在本地体验这一功能时需要启动两台eventmesh实例,同时要修改`eventmesh-runtime`目录下的`eventmesh.properties`文件中的端口配置,避免端口冲突。便于下文描述,event-bridge特性按照上图信息进行表述。 + +## 01 远程订阅 + +**描述**:向cluster2 eventmesh发起远程订阅指令,cluster2 eventmesh收到指令后会携带订阅信息调用cluster1 eventmesh的本地订阅接口 + +**URL**: http://{cluster2 address}/eventmesh/subscribe/remote + +**请求方式**:POST + +**请求参数:**application/json 格式 + +| 参数名 | 类型 | 是否必填 | 说明 | +| ------------- | ------ | -------- | ------------------------------------------------------------ | +| url | String | 是 | 标识订阅url信息,暂时无用,后续可移除,目前仅为强校验,实际会被(/eventmesh/bridge/publish)替换 | +| consumerGroup | String | 是 | 标识消费组信息,实际会被cluster2的eventmesh配置信息替换 | +| topic | List | 是 | 标识订阅信息列表 | +| mode | String | 是 | 标识消费模式,分为集群模式和广播模式 | +| topic | String | 是 | 标识订阅的topic | +| type | String | 是 | 标识消费类型,分为同步和异步 | +| remoteMesh | String | 否 | 标识远程mesh地址,优先根据topic从注册中心获取,获取不到使用该字段替换 | + +**请求样例:** + +```json +{ + "url": "http://127.0.0.1:8088/sub/test", + "consumerGroup": "TEST-GROUP", + "topic": [ + { + "mode": "CLUSTERING", + "topic": "TEST-TOPIC-HTTP-ASYNC", + "type": "ASYNC" + } + ], + "remoteMesh" : "http://127.0.0.1:10105/eventmesh/subscribe/local" +} +``` + +## 02 本地订阅 + +**描述**:向cluster2的EventMesh实例发起本地订阅指令,cluster2的EventMesh收到订阅指令后会启动本地监听从event store收下来的消息,并推送给订阅信息中的url。 + +**URL**: http://{cluster2 address}/eventmesh/subscribe/local + +**请求方式**:POST + +**请求参数:**application/json 格式 + +| 参数名 | 类型 | 是否必填 | 说明 | +| ------------- | ------ | -------- | ------------------------------------ | +| url | String | 是 | 标识订阅url信息 | +| consumerGroup | String | 是 | 标识消费组信息 | +| topic | List | 是 | 标识订阅信息列表 | +| mode | String | 是 | 标识消费模式,分为集群模式和广播模式 | +| topic | String | 是 | 标识订阅的topic | +| type | String | 是 | 标识消费类型,分为同步和异步 | + +**请求样例:** + +```JSON +{ + "url": "http://127.0.0.1:8088/sub/test", + "consumerGroup": "TEST-GROUP", + "topic": [ + { + "mode": "CLUSTERING", + "topic": "TEST-TOPIC-HTTP-ASYNC", + "type": "ASYNC" + } + ] +} +``` + +## 03 发送消息 + +**描述**:向cluster1的EventMesh实例发送消息,cluster1的EventMesh收到消息后会发送到event store,再从event store收下来消息推送给cluster2的EventMesh url `/eventmesh/bridge/publish`。 + +**URL**: http://{cluster1 address}/eventmesh/publish/TEST-TOPIC-HTTP-ASYNC + +**请求方式**:POST + +**请求参数:**application/json 格式 + +**请求样例:** + +```json +{ + "name":"test", + "age":"19" +} +``` + +## 04远程去订阅 + +**描述**:向cluster2的EventMesh实例发送去除订阅指令,cluster2的EventMesh收到指令后会发送cluster1的EventMesh,cluster1的EventMesh会本地执行去除订阅 + +**URL**: http://{cluster2 address}/eventmesh/unsubscribe/remote + +**请求方式**:POST + +**请求参数:**application/json 格式 + +| 参数名 | 类型 | 是否必填 | 说明 | +| ------------- | ------ | -------- | ------------------------------------------------------------ | +| url | String | 是 | 标识要去除订阅url信息,暂时无用,后续可移除,目前仅为强校验,实际会被(/eventmesh/bridge/publish)替换 | +| consumerGroup | String | 是 | 标识要去除的消费组信息,实际会使用EventMesh cluster2的group信息替换 | +| topic | List | 是 | 标识订阅topic信息列表 | + +**请求样例:** + +```json +{ + "consumerGroup": "EventMeshTest-consumerGroup", + "url": "http://127.0.0.1:8088/sub/test", + "topic": [ + "TEST-TOPIC-HTTP-ASYNC" + ] +} +``` + +## 05本地去订阅 + +**描述**:向cluster2的EventMesh实例发送去除订阅指令,cluster2的EventMesh收到指令后会本地执行去除订阅 + +**URL**: http://{cluster2 address}/eventmesh/unsubscribe/local + +**请求方式**:POST + +**请求参数:**application/json 格式 + +| 参数名 | 类型 | 是否必填 | 说明 | +| ------------- | ------ | -------- | ---------------------- | +| url | String | 是 | 标识要去除订阅url信息 | +| consumerGroup | String | 是 | 标识要去除的消费组信息 | +| topic | List | 是 | 标识订阅topic信息列表 | + +**请求样例:** + +```json +{ + "consumerGroup": "EventMeshTest-consumerGroup", + "url": "http://127.0.0.1:8088/sub/test", + "topic": [ + "TEST-TOPIC-HTTP-ASYNC" + ] +} +``` \ No newline at end of file diff --git a/docs/en/design-document/10-knative-connector.md b/docs/en/design-document/10-knative-connector.md new file mode 100644 index 0000000000..2c98e147a8 --- /dev/null +++ b/docs/en/design-document/10-knative-connector.md @@ -0,0 +1,93 @@ +# Knative Connector + +## Prerequisite +### Create Knative Source and Sink +We use the *cloudevents-player* [Knative service](https://knative.dev/docs/serving/) as an example. If you do not know how to create *cloudevents-player* Knative service as source and sink, please follow the steps in this [link](https://knative.dev/docs/getting-started/first-source/#creating-your-first-source). + + +### Set up EventMesh Configuration +- Add the following lines to [eventmesh-starter/build.gradle](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-starter/build.gradle) file. +``` +plugins { + id 'application' +} + +application { + mainClass = project.hasProperty("mainClass") ? project.getProperty("mainClass") : 'org.apache.eventmesh.starter.StartUp' + applicationDefaultJvmArgs = [ + '-Dlog4j.configurationFile=../eventmesh-runtime/conf/log4j2.xml', '-Deventmesh.log.home=../eventmesh-runtime/logs', '-Deventmesh.home=../eventmesh-runtime', '-DconfPath=../eventmesh-runtime/conf' + ] +} + +dependencies { + implementation project(":eventmesh-connector-plugin:eventmesh-connector-knative") + implementation project(":eventmesh-runtime") +} +``` +- Add the following lines to [eventmesh-examples/build.gradle](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-examples/build.gradle) file. +``` +plugins { + id 'application' +} + +application { + mainClass = project.hasProperty("mainClass") ? project.getProperty("mainClass") : 'NULL' +} +``` +- Set ```eventMesh.connector.plugin.type=knative``` in [eventmesh-runtime/conf/eventmesh.properties](https://github.com/pchengma/incubator-eventmesh/blob/master/eventmesh-runtime/conf/eventmesh.properties) file. + +## Demo +### Publish an Event Message from Knative and Subscribe from EventMesh +#### Step 1: Start an Eventmesh-Runtime Server +```bash +$ cd eventmesh-starter +$ ../gradlew -PmainClass=org.apache.eventmesh.starter.StartUp run +``` + +#### Step 2: Publish an Event Message from Knative +```bash +$ curl -i http://cloudevents-player.default.127.0.0.1.sslip.io -H "Content-Type: application/json" -H "Ce-Id: 123456789" -H "Ce-Specversion: 1.0" -H "Ce-Type: some-type" -H "Ce-Source: command-line" -d '{"msg":"Hello CloudEvents!"}' +``` + +#### Step 3: Subscribe from an EventMesh +- Set ```public static final String EVENTMESH_HTTP_ASYNC_TEST_TOPIC = "messages";``` in [ExampleConstants.java](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-examples/src/main/java/org/apache/eventmesh/common/ExampleConstants.java) file. +```bash +$ cd eventmesh-examples +$ ../gradlew -PmainClass=org.apache.eventmesh.http.demo.sub.SpringBootDemoApplication run +``` + +#### Expected Result +The following message with ```data``` field as ```Hello CloudEvents!``` will be printed on the console of EventMesh server. +```bash +2022-09-05 16:37:58,237 INFO [eventMesh-clientManage-] DefaultConsumer(DefaultConsumer.java:60) - \ +[{"event":{"attributes":{"datacontenttype":"application/json","id":"123456789","mediaType":"application/json",\ +"source":"command-line","specversion":"1.0","type":"some-type"},"data":{"msg":"Hello CloudEvents!"},"extensions":{}},\ +"id":"123456789","receivedAt":"2022-09-05T10:37:49.537658+02:00[Europe/Madrid]","type":"RECEIVED"}] +``` + +### Publish an Event Message from EventMesh and Subscribe from Knative +#### Step 1: Start an Eventmesh-Runtime Server +```bash +$ cd eventmesh-starter +$ ../gradlew -PmainClass=org.apache.eventmesh.starter.StartUp run +``` + +#### Step 2: Publish an Event Message from EventMesh +We use a test program to demo this function. +```bash +$ cd eventmesh-connector-plugin/eventmesh-connector-knative +$ ../../gradlew clean test --tests KnativeProducerImplTest.testPublish +``` + +#### Step 3: Subscribe from Knative +```bash +$ curl http://cloudevents-player.default.127.0.0.1.sslip.io/messages +``` + +#### Expected Result +The following message with ```data``` field as ```Hello Knative from EventMesh!``` will be printed on the console of EventMesh server. +```bash +2022-09-05 16:52:41,633 INFO [eventMesh-clientManage-] DefaultConsumer(DefaultConsumer.java:60) - \ +[{"event":{"attributes":{"datacontenttype":"application/json","id":"1234","mediaType":"application/json",\ +"source":"java-client","specversion":"1.0","type":"some-type"},"data":{"msg":["Hello Knative from EventMesh!"]},"extensions":{}},"id":"1234","receivedAt":"2022-09-05T10:52:32.999273+02:00[Europe/Madrid]","type":"RECEIVED"}] +``` \ No newline at end of file diff --git a/docs/en/design-document/11-prometheus.md b/docs/en/design-document/11-prometheus.md new file mode 100644 index 0000000000..1bc6e0e554 --- /dev/null +++ b/docs/en/design-document/11-prometheus.md @@ -0,0 +1,24 @@ +# Observe Metrics with Prometheus + +## Prometheus + +[Prometheus](https://prometheus.io/docs/introduction/overview/) is an open-source system monitoring and alerting toolkit that collects and stores the metrics as time-series data. EventMesh exposes a collection of metrics data that could be scraped and analyzed by Prometheus. Please follow [the "First steps with Prometheus" tutorial](https://prometheus.io/docs/introduction/first_steps/) to download and install the latest release of Prometheus. + +## Edit Prometheus Configuration + +The `eventmesh-runtime/conf/prometheus.yml` configuration file specifies the port of the metrics HTTP endpoint. The default metrics port is `19090`. + +```properties +eventMesh.metrics.prometheus.port=19090 +``` + +Please refer to [the Prometheus configuration guide](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config) to add the EventMesh metrics as a scrape target in the configuration file. Here's the minimum configuration that creates a job with the name `eventmesh` and the endpoint `http://localhost:19090`: + +```yaml +scrape_configs: + - job_name: "eventmesh" + static_configs: + - targets: ["localhost:19090"] +``` + +Please navigate to the Prometheus dashboard (e.g. `http://localhost:9090`) to view the list of metrics exported by EventMesh, which are prefixed with `eventmesh_`. diff --git a/docs/en/design-document/12-zipkin.md b/docs/en/design-document/12-zipkin.md new file mode 100644 index 0000000000..f4d07252d7 --- /dev/null +++ b/docs/en/design-document/12-zipkin.md @@ -0,0 +1,38 @@ +# Collect Trace with Zipkin + +## Zipkin + +Distributed tracing is a method used to profile and monitor applications built with microservices architecture. Distributed tracing helps pinpoint where failures occur and what causes poor performance. + +[Zipkin](https://zipkin.io) is a distributed tracing system that helps collect timing data needed to troubleshoot latency problems in service architectures. EventMesh exposes a collection of trace data that could be collected and analyzed by Zipkin. Please follow [the "Zipkin Quickstart" tutorial](https://zipkin.io/pages/quickstart.html) to download and install the latest release of Zipkin. + +## Configuration + +To enable the trace exporter of EventMesh Runtime, set the `eventMesh.server.trace.enabled` field in the `conf/eventmesh.properties` file to `true`. + +```conf +# Trace plugin +eventMesh.server.trace.enabled=true +eventMesh.trace.plugin=zipkin +``` + +To customize the behavior of the trace exporter such as timeout or export interval, edit the `exporter.properties` file. + +```conf +# Set the maximum batch size to use +eventmesh.trace.max.export.size=512 +# Set the queue size. This must be >= the export batch size +eventmesh.trace.max.queue.size=2048 +# Set the max amount of time an export can run before getting(TimeUnit=SECONDS) +eventmesh.trace.export.timeout=30 +# Set time between two different exports (TimeUnit=SECONDS) +eventmesh.trace.export.interval=5 +``` + +To send the exported trace data to Zipkin, edit the `eventmesh.trace.zipkin.ip` and `eventmesh.trace.zipkin.port` fields in the `conf/zipkin.properties` file to match the configuration of the Zipkin server. + +```conf +# Zipkin's IP and Port +eventmesh.trace.zipkin.ip=localhost +eventmesh.trace.zipkin.port=9411 +``` diff --git a/docs/en/design-document/13-jaeger.md b/docs/en/design-document/13-jaeger.md new file mode 100644 index 0000000000..e9452c3554 --- /dev/null +++ b/docs/en/design-document/13-jaeger.md @@ -0,0 +1,44 @@ +# Collect Trace with Jaeger + +## Jaeger + +[Jaeger](https://www.jaegertracing.io/), inspired by [Dapper](https://research.google.com/pubs/pub36356.html) and [OpenZipkin](https://zipkin.io/), is a distributed tracing platform created by [Uber Technologies](https://uber.github.io/) and donated to [Cloud Native Computing Foundation](https://cncf.io/). It can be used for monitoring microservices-based distributed systems. + +For the installation of Jaeger, you can refer to the [official documentation](https://www.jaegertracing.io/docs/latest/getting-started/) of Jaeger. It is recommended to use docker image `jaegertracing/all-in-one` to quickly build the environment for testing. + +## Configuration + +To enable the trace exporter of EventMesh Runtime, set the `eventMesh.server.trace.enabled` field in the `conf/eventmesh.properties` file to `true`. + +```conf +# Trace plugin +eventMesh.server.trace.enabled=true +eventMesh.trace.plugin=jaeger +``` + +To customize the behavior of the trace exporter such as timeout or export interval, edit the `exporter.properties` file. + +```conf +# Set the maximum batch size to use +eventmesh.trace.max.export.size=512 +# Set the queue size. This must be >= the export batch size +eventmesh.trace.max.queue.size=2048 +# Set the max amount of time an export can run before getting(TimeUnit=SECONDS) +eventmesh.trace.export.timeout=30 +# Set time between two different exports (TimeUnit=SECONDS) +eventmesh.trace.export.interval=5 +``` + +To send the exported trace data to Jaeger, edit the `eventmesh.trace.jaeger.ip` and `eventmesh.trace.jaeger.port` fields in the `conf/jaeger.properties` file to match the configuration of the Jaeger server. + +```conf +# Jaeger's IP and Port +eventmesh.trace.jaeger.ip=localhost +eventmesh.trace.jaeger.port=14250 +``` + +## Migrating from Zipkin + +Collector service exposes Zipkin compatible REST API `/api/v1/spans` which accepts both Thrift and JSON. Also there is `/api/v2/spans` for JSON and Proto. + +So you can also use the `eventmesh-trace-zipkin` plugin to collect trace with Jaeger. Please refer to the `eventmesh-trace-zipkin` documentation for the specific configuration. By default this feature in Jaeger is disabled. It can be enabled with `--collector.zipkin.host-port=:9411`. \ No newline at end of file diff --git a/docs/en/design-document/_category_.json b/docs/en/design-document/_category_.json new file mode 100644 index 0000000000..f9283e2f00 --- /dev/null +++ b/docs/en/design-document/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 6, + "label": "Design Document", + "collapsed": false +} diff --git a/docs/en/design-document/webhook.md b/docs/en/design-document/webhook.md new file mode 100644 index 0000000000..13ec4de064 --- /dev/null +++ b/docs/en/design-document/webhook.md @@ -0,0 +1,270 @@ + +## Webhook usage process +#### The first step: Configure webhook related information in eventmesh and start + +##### Configuration +``` +# Whether to start the webhook admin service +eventMesh.webHook.admin.start=true + +# webhook event configuration storage mode. But currently only supports file and nacos +eventMesh.webHook.operationMode=file + +# The file path of fileMode. If you write #{eventMeshHome}, in the eventMesh root directory +eventMesh.webHook.fileMode.filePath= #{eventMeshHome}/webhook + +# The nacos storage mode. The configuration naming rule is eventMesh.webHook.nacosMode.{nacos native configuration key} For the specific configuration, please see [nacos github api](https://github.com/alibaba/nacos/blob/develop/api/src/main/java /com/alibaba/nacos/api/SystemPropertyKeyConst.java) +## address of nacos +eventMesh.webHook.nacosMode.serverAddr=127.0.0.1:8848 + +# webhook eventcloud send mode. Same as eventMesh.connector.plugin.type configuration +eventMesh.webHook.producer.connector=standalone +``` + +#### The second step: Add webhook configuration information + +Configuration information description + +```java + /** + * The path called by the manufacturer. Manufacturer event call address, [http or https]://[domain or IP]:[port]/webhook/[callbackPath] + * for example: http://127.0.0.1:10504/webhook/test/event , The full url needs to be filled in the manufacturer call input + * callbackPath is the only + */ + private String callbackPath; + + /** + * manufacturer name, like github + */ + private String manufacturerName; + + /** + * webhook event name, like rep-push + */ + private String manufacturerEventName; + + /** + * http header content type + */ + private String contentType = "application/json"; + + /** + * description of this WebHookConfig + */ + private String description; + + /** + * secret key, for authentication + */ + private String secret; + + /** + * userName, for HTTP authentication + */ + private String userName; + + /** + * password, for HTTP authentication + */ + private String password; + + + /** + * roll out event name, like topic to mq + */ + private String cloudEventName; + + /** + * roll out data format -> CloudEvent serialization mode + * If HTTP protocol is used, the request header contentType needs to be marked + */ + private String dataContentType = "application/json";; + + /** + * source of event + */ + private String cloudEventSource; + + /** + * id of cloudEvent, like uuid/manufacturerEventId + */ + private String cloudEventIdGenerateMode; + +``` + +##### Add webhook config + +path: /webhook/insertWebHookConfig +method: POST +contentType: application/json + +input params: +| field | desc | type | necessary | default | +| -- | -- | -- | -- | -- | +| callbackPath | call address, unique address | string | Y | null | +| manufacturerName | manufacturer name | string | Y | null | +| manufacturerEventName | manufacturer EventName | string | Y | null | +| contentType | http connettype | string | N | application/json | +| description | configuration instructions | string | N | null | +| secret | signature string | string | N | null | +| userName | username | string | N | null | +| password | password | string | N | null | +| cloudEventName | cloudEvent name | string | Y | null | +| cloudEventSource | cloudEvent source | string | Y | null | +| cloudEventIdGenerateMode | cloudEvent event object identification method, uuid or event id | string | N manufacturerEventId | + +E.g: + +```json + +{ + "callbackPath":"/webhook/github/eventmesh/all", + "manufacturerName":"github", + "manufacturerEventName":"all", + "secret":"eventmesh", + "cloudEventName":"github-eventmesh", + "cloudEventSource":"github" +} + +``` + +Output params: 1 for success, 0 for failure + +##### delete webhook config +path: /webhook/deleteWebHookConfig +method: POST +contentType: application/json + +input params: +| field | desc | type | necessary | default | +| -- | -- | -- | -- | -- | +| callbackPath | call address, unique address | string | Y | null | + + +E.g: + +```json + +{ + "callbackPath":"/webhook/github/eventmesh/all" +} + +``` + +Output params: 1 for success, 0 for failure + +##### select WebHookConfig by callbackPath +path: /webhook/queryWebHookConfigById +method: POST +contentType: application/json + +input params: +| field | desc | type | necessary | default | +| -- | -- | -- | -- | -- | +| callbackPath | call address, unique address | string | Y | null | + + +E.g: + +```json + +{ + "callbackPath":"/webhook/github/eventmesh/all" +} + +``` + +Output params: +| field | desc | type | necessary | default | +| -- | -- | -- | -- | -- | +| callbackPath | call address, unique address | string | Y | null | +| manufacturerName | manufacturer name | string | Y | null | +| manufacturerEventName | manufacturer event name | string | Y | null | +| contentType | http connettype | string | N | application/json | +| description | configuration instructions | string | N | null | +| secret | signature key | string | N | null | +| userName | user name | string | N | null | +| password | password | string | N | null | +| cloudEventName | cloudEvent name | string | Y | null | +| cloudEventSource | cloudEvent source | string | Y | null | +| cloudEventIdGenerateMode | cloudEvent event object identification method, uuid or event id | string | N | manufacturerEventId | + + +##### 通过manufacturer查询WebHookConfig列表 +path: /webhook/queryWebHookConfigByManufacturer +method: POST +contentType: application/json + +input params: +| field | desc | type | necessary | default | +| -- | -- | -- | -- | -- | +| manufacturerName | manufacturer name | string | Y | null | + + +E.g: + +```json + +{ + "manufacturerName":"github" +} + +``` + +Output params: +| field | desc | type | necessary | default | +| -- | -- | -- | -- | -- | +| callbackPath | call address, unique address | string | Y | null | +| manufacturerName | manufacturer name | string | Y | null | +| manufacturerEventName | manufacturer event name | string | Y | null | +| contentType | http connettype | string | N | application/json | +| description | configuration instructions | string | N | null | +| secret | signature key | string | N | null | +| userName | user name | string | N | null | +| password | password | string | N | null | +| cloudEventName | cloudEvent name | string | Y | null | +| cloudEventSource | cloudEvent source | string | Y | null | +| cloudEventIdGenerateMode | cloudEvent event object identification method, uuid or event id | string | N | manufacturerEventId | + + +#### The third step: Check if the configuration is successful + +1. file storage mode. Please go to the eventMesh.webHook.fileMode.filePath directory to view. filename callbackPath. + +2. nacos storage mode. Please go to the nacos service configured by eventMesh.webHook.nacosMode.serverAddr to see. + +#### The fourth step: Configure the consumer of cloudevent + +#### The fifth step: Configure webhook related information in the manufacturer + +> For manufacturer's operation, please refer to [Manufacturer's webhook operation instructions] . + +## Manufacturer's webhook operation instructions + +### github sign up + +#### The first step: Enter the corresponding project + +#### The second step: click setting + +![](../../images/design-document/webhook/webhook-github-setting.png) + +#### The third step: click Webhooks + +![](../../images/design-document/webhook/webhook-github-webhooks.png) + +#### The fourth step: Click on Add webhook + +![](../../images/design-document/webhook/webhook-github-add.png) + +#### The fifth step: Fill in the webhook information + +![](../../images/design-document/webhook/webhook-github-info.png) + +Payload URL: Service address and pahts. [http or https]://[domain or IP]:[port]/webhook/[callbackPath] +Content type: http header content type +secret: signature string + + + + diff --git a/docs/en/features/architecture.md b/docs/en/features/architecture.md deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs/en/features/request-response-call.md b/docs/en/features/request-response-call.md deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs/en/instruction/01-store-with-docker.md b/docs/en/instruction/01-store-with-docker.md new file mode 100644 index 0000000000..8c102b2496 --- /dev/null +++ b/docs/en/instruction/01-store-with-docker.md @@ -0,0 +1,71 @@ +# Guidelines of eventmesh-store with Docker + +## Dependencies + +``` +64-bit OS,we recommend Linux/Unix; +64-bit JDK 1.8+; +Gradle 7.0+, we recommend 7.0.* +4g+ available disk to deploy eventmesh-store +If you choose standalone mode, you could skip this file and go to the next step: Start Eventmesh-Runtime; if not, you could choose RocketMQ as the store layer. +``` + + +## Download + +Download the Binary code (recommended: 4.9.*) from [RocketMQ Official](https://rocketmq.apache.org/dowloading/releases/). Here we take 4.9.2 as an example. + +``` +unzip rocketmq-all-4.9.2-bin-release.zip +cd rocketmq-4.9.2/ +``` + + +## Deploy + +- #### Start Name Server + +``` +nohup sh bin/mqnamesrv & +tail -f ~/logs/rocketmqlogs/namesrv.log +``` + +- #### Start Broker + +``` +nohup sh bin/mqbroker -n localhost:9876 & +tail -f ~/logs/rocketmqlogs/broker.log +``` + +The deployment of eventmesh-store has finished, please go to the next step: [Start Eventmesh-Runtime](02-runtime.md) + + + +## Deploy +Pull RocketMQ image from Docker Hub: + +```shell +#获取namesrv镜像 +sudo docker pull rocketmqinc/rocketmq-namesrv:4.5.0-alpine +#获取broker镜像 +sudo docker pull rocketmqinc/rocketmq-broker:4.5.0-alpine +``` + +Start namesrv and broker + +```shell +#运行namerv容器 +sudo docker run -d -p 9876:9876 -v `pwd`/data/namesrv/logs:/root/logs -v `pwd`/data/namesrv/store:/root/store --name rmqnamesrv rocketmqinc/rocketmq-namesrv:4.5.0-alpine sh mqnamesrv + +#运行broker容器 +sudo docker run -d -p 10911:10911 -p 10909:10909 -v `pwd`/data/broker/logs:/root/logs -v `pwd`/data/broker/store:/root/store --name rmqbroker --link rmqnamesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" rocketmqinc/rocketmq-broker:4.5.0-alpine sh mqbroker -c ../conf/broker.conf +``` + +Please note that the **rocketmq-broker ip** is **pod ip**. If you want to modify this ip, you can set it your custom value in **broker.conf**。 + + +By now, the deployment of eventmesh-store has finished, please go to the next step: [Start Eventmesh-Runtime Using Docker](02-runtime-with-docker.md) + + +## Reference +For more details about RocketMQ,please refer to diff --git a/docs/en/instruction/01-store.md b/docs/en/instruction/01-store.md new file mode 100644 index 0000000000..ab281c7cab --- /dev/null +++ b/docs/en/instruction/01-store.md @@ -0,0 +1,44 @@ +# Guidelines of eventmesh-store + +## Dependencies + +``` +64-bit OS,we recommend Linux/Unix; +64-bit JDK 1.8+; +Gradle 7.0+, we recommend 7.0.* +4g+ available disk to deploy eventmesh-store +If you choose standalone mode, you could skip this file and go to the next step: Start Eventmesh-Runtime; if not, you could choose RocketMQ as the store layer. +``` + + +## Download + +Download the Binary code (recommended: 4.9.*) from [RocketMQ Official](https://rocketmq.apache.org/dowloading/releases/). Here we take 4.9.2 as an example. + +``` +unzip rocketmq-all-4.9.2-bin-release.zip +cd rocketmq-4.9.2/ +``` + + +## Deploy + +- #### Start Name Server + +``` +nohup sh bin/mqnamesrv & +tail -f ~/logs/rocketmqlogs/namesrv.log +``` + +- #### Start Broker + +``` +nohup sh bin/mqbroker -n localhost:9876 & +tail -f ~/logs/rocketmqlogs/broker.log +``` + +The deployment of eventmesh-store has finished, please go to the next step: [Start Eventmesh-Runtime](02-runtime.md) + + +## Reference +For more details about RocketMQ, please refer to diff --git a/docs/en/instruction/02-runtime-with-docker.md b/docs/en/instruction/02-runtime-with-docker.md new file mode 100644 index 0000000000..7da3e2a433 --- /dev/null +++ b/docs/en/instruction/02-runtime-with-docker.md @@ -0,0 +1,107 @@ +# EventMesh Runtime (Docker) + +The documentation introduces the steps to install the latest release of EventMesh Runtime with Docker and connect to Apache RocketMQ. It's recommended to use a Linux-based system with [Docker Engine](https://docs.docker.com/engine/install/). Please follow the [Docker tutorial](https://docs.docker.com/get-started/) to get familiar with the basic concepts (registry, volume, etc.) and commands of Docker. + + +## Dependencies +``` +64-bit OS,we recommend Linux/Unix; +64-bit JDK 1.8+; +Gradle 7.0+, we recommend 7.0.* +4g+ available disk to deploy eventmesh-store +If you choose standalone mode, you could skip this file and go to the next step: Start Eventmesh-Runtime; if not, you could choose RocketMQ as the store layer. +``` + +## Pull EventMesh Image + +Download the pre-built image of [`eventmesh`](https://hub.docker.com/r/eventmesh/eventmesh) from Docker Hub with `docker pull`: + +```console +$ sudo docker pull eventmesh/eventmesh:v1.4.0 +``` + +To verify that the `eventmesh/eventmesh` image is successfully installed, list the downloaded images with `docker images`: + +```console +$ sudo docker images +eventmesh/eventmesh v1.4.0 6e2964599c78 2 weeks ago 937MB +``` + +## Edit Configuration + +Edit the `eventmesh.properties` to change the configuration (e.g. TCP port, client blacklist) of EventMesh Runtime. To integrate RocketMQ as a connector, these two configuration files should be created: `eventmesh.properties` and `rocketmq-client.properties`. + +```shell +sudo mkdir -p /data/eventmesh/rocketmq/conf +cd /data/eventmesh/rocketmq/conf +sudo touch eventmesh.properties +sudo touch rocketmq-client.properties +``` + +### `eventmesh.properties` + +The `eventmesh.properties` file contains the properties of EventMesh runtime environment and integrated plugins. Please refer to the [default configuration file](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-runtime/conf/eventmesh.properties) for the available configuration keys. + +```shell +sudo vim eventmesh.properties +``` + +| Configuration Key | Default Value | Description | +|-|-|-| +| `eventMesh.server.http.port` | 10105 | EventMesh HTTP server port | +| `eventMesh.server.tcp.port` | 10000 | EventMesh TCP server port | +| `eventMesh.server.grpc.port` | 10205 | EventMesh gRPC server port | + +### `rocketmq-client.properties` + +The `rocketmq-client.properties` file contains the properties of the Apache RocketMQ nameserver. + +```shell +sudo vim rocketmq-client.properties +``` + +Please refer to the [default configuration file](https://github.com/apache/incubator-eventmesh/blob/1.3.0/eventmesh-runtime/conf/rocketmq-client.properties) and change the value of `eventMesh.server.rocketmq.namesrvAddr` to the nameserver address of RocketMQ. + +| Configuration Key | Default Value | Description | +|-|-|-| +| `eventMesh.server.rocketmq.namesrvAddr` | `127.0.0.1:9876;127.0.0.1:9876` | The address of RocketMQ nameserver | + +## Run and Manage EventMesh Container + +Run an EventMesh container from the `eventmesh/eventmesh` image with the `docker run` command. The `-p` option of the command binds the container port with the host machine port. The `-v` option of the command mounts the configuration files from files in the host machine. + +```shell +sudo docker run -d -p 10000:10000 -p 10105:10105 \ +-v /data/eventmesh/rocketmq/conf/eventmesh.properties:/data/app/eventmesh/conf/eventmesh.properties \ +-v /data/eventmesh/rocketmq/conf/rocketmq-client.properties:/data/app/eventmesh/conf/rocketmq-client.properties \ +eventmesh/eventmesh:v1.4.0 +``` + +The `docker ps` command lists the details (id, name, status, etc.) of the running containers. The container id is the unique identifier of the container. + +```console +$ sudo docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + eventmesh/eventmesh:v1.4.0 "/bin/sh -c 'sh star…" About a minute ago Up About a minute 0.0.0.0:10000->10000/tcp, :::10000->10000/tcp, 0.0.0.0:10105->10105/tcp, :::10105->10105/tcp +``` + +To connect to the EventMesh container: + +```shell +sudo docker exec -it [container id or name] /bin/bash +``` + +To read the log of the EventMesh container: + +```shell +tail -f ../logs/eventmesh.out +``` + +To stop or remove the container: + +```shell +sudo docker stop [container id or name] + +sudo docker rm -f [container id or name] +``` + diff --git a/docs/en/instruction/02-runtime.md b/docs/en/instruction/02-runtime.md new file mode 100644 index 0000000000..66bfca7f6c --- /dev/null +++ b/docs/en/instruction/02-runtime.md @@ -0,0 +1,107 @@ +# EventMesh Runtime + +EventMesh Runtime is the core component of Apache EventMesh (Incubating). It is the middleware that transmits events between producers and consumers. The documentation introduces the step to install and start the latest release of EventMesh Runtime in the local or test environment. The EventMesh Runtime requires a Linux-based system with JDK (Java Development Kit) 8+. + +Here, we take JDK 8 as an example. JDK 8 could be installed with the system package manager or the [openjdk:8-jdk](https://hub.docker.com/_/openjdk) Docker image. + + +## 1 Run on your local machine + +### 1.1 Dependencies + +``` +64-bit OS,we recommend Linux/Unix; +64-bit JDK 1.8+; +Gradle 7.0+, we recommend 7.0.* +4g+ available disk to deploy eventmesh-store +If you choose standalone mode, you could skip this file and go to the next step: Start Eventmesh-Runtime; if not, you could choose RocketMQ as the store layer. +``` + +### 1.2 Download Source Code + +Gradle is the build automation tool used by Apache EventMesh (Incubating). Please refer to the [offical guide](https://docs.gradle.org/current/userguide/installation.html) to install the latest release of Gradle. + +Download and extract the source code of the latest release from [EventMesh download](https://eventmesh.apache.org/download). + +```console +wget https://dlcdn.apache.org/incubator/eventmesh/{version}-incubating/apache-eventmesh-{version}-incubating-source.tar.gz + +tar -xvzf apache-eventmesh-1.5.0-incubating-source.tar.gz +``` + +Build the source code with Gradle. + +```console +cd apache-eventmesh-1.5.0-incubating-source +gradle clean dist +``` + +Edit the `eventmesh.properties` to change the configuration (e.g. TCP port, client blacklist) of EventMesh Runtime. + +```console +cd dist +vim conf/eventmesh.properties +``` + +Execute the `start.sh` script to start the EventMesh Runtime server. + +```console +bash bin/start.sh +``` + +### 1.3 Build and Load Plugins + +Apache EventMesh (Incubating) introduces the SPI (Service Provider Interface) mechanism, which enables EventMesh to discover and load the plugins at runtime. The plugins could be installed with these methods: + +- Gradle Dependencies: Declare the plugins as the build dependencies in `eventmesh-starter/build.gradle`. + +```gradle +dependencies { + implementation project(":eventmesh-runtime") + + // Example: Load the RocketMQ plugin + implementation project(":eventmesh-connector-plugin:eventmesh-connector-rocketmq") +} +``` + +- Plugin directory: EventMesh loads the plugins in the `dist/plugin` directory based on `eventmesh.properties`. The `installPlugin` task of Gradle builds and moves the plugins into the `dist/plugin` directory. + +```console +gradle installPlugin +``` + + +## 2 Remote deployment +### 2.1 Dependencies + +``` +64-bit OS,we recommend Linux/Unix; +64-bit JDK 1.8+; +Gradle 7.0+, we recommend 7.0.* +4g+ available disk to deploy eventmesh-store +If you choose standalone mode, you could skip this file and go to the next step: Start Eventmesh-Runtime; if not, you could choose RocketMQ as the store layer. +``` + +### 2.2 Download +Download and extract the executable binaries of the latest release from [EventMesh download](https://eventmesh.apache.org/download). + +```console +wget https://dlcdn.apache.org/incubator/eventmesh/1.5.0-incubating/apache-eventmesh-1.5.0-incubating-bin.tar.gz + +tar -xvzf apache-eventmesh-1.5.0-incubating-bin.tar.gz +``` + +### 2.3 Deploy +Edit the `eventmesh.properties` to change the configuration (e.g. TCP port, client blacklist) of EventMesh Runtime. The executable binaries contain all plugins in the bundle, thus there's no need to build them from source code. + +```console +cd apache-eventmesh-1.5.0-incubating +vim conf/eventmesh.properties +``` + +Execute the `start.sh` script to start the EventMesh Runtime server. + +```console +bash bin/start.sh +``` + diff --git a/docs/en/instruction/03-demo.md b/docs/en/instruction/03-demo.md new file mode 100644 index 0000000000..0b99d47b74 --- /dev/null +++ b/docs/en/instruction/03-demo.md @@ -0,0 +1,152 @@ +# Run our demos + +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.eventmesh/eventmesh-sdk-java/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.apache.eventmesh/eventmesh-sdk-java) + +> EventMesh-sdk-java as the client,and comminucate with eventmesh-runtime,to finish the message sub and pub +> +> EventMesh-sdk-java support both async and broadcast. +> +> EventMesh-sdk-java support HTTP, TCP and gRPC. + +The test demos of TCP, HTTP 和 GRPC are in the module **eventmesh-examples** + +## 1 TCP DEMO + +### 1.1 ASYNC + +- Start consumer to subscribe the topic (we have created the TEST-TOPIC-TCP-ASYNC by default, you can also create other topic to test) + +``` +Run the main method of org.apache.eventmesh.tcp.demo.sub.eventmeshmessage.AsyncSubscribe +``` + +- Start producer to publish async message + +``` +Run the main method of org.apache.eventmesh.tcp.demo.pub.eventmeshmessage.AsyncPublish +``` + +### 1.2 BROADCAST + +- Start subscriber to subscribe the topic (we have created the TEST-TOPIC-TCP-BROADCAST by default, you can also create other topic to test) + +``` +Run the main method of org.apache.eventmesh.tcp.demo.sub.eventmeshmessage.AsyncSubscribeBroadcast +``` + +- Start publisher to publish async message + +``` +Run the main method of org.apache.eventmesh.tcp.demo.pub.eventmeshmessage.AsyncPublishBroadcast +``` + +More information about EventMesh-TCP, please refer to [EventMesh TCP](/docs/en/sdk-java/03-tcp.md) + + +## 2 HTTP DEMO + + +### 2.1 ASYNC + +- The subscriber is a SpringBoot demo, so run this demo to start subscriber (we have created the topic TEST-TOPIC-HTTP-ASYNC by default, you can also create other topic to test) + +``` +Run the main method of org.apache.eventmesh.http.demo.sub.SpringBootDemoApplication +``` + +- Start publisher to publish message + +``` +Run the main method of org.apache.eventmesh.http.demo.pub.eventmeshmessage.AsyncPublishInstance +``` +More information about EventMesh-HTTP, please refer to [EventMesh HTTP](/docs/en/sdk-java/02-http.md) + +## 3 GRPC DEMO + +### 3.1 ASYNC PUBLISH & WEBHOOK SUBSCRIBE + +- Start publisher to publish message (we have created the topic TEST-TOPIC-GRPC-ASYNC by default, you can also create other topic to test) + +``` +Run the main method of org.apache.eventmesh.grpc.pub.eventmeshmessage.AsyncPublishInstance +``` + +- Start webhook subscriber + +``` +Run the main method of org.apache.eventmesh.grpc.sub.app.SpringBootDemoApplication +``` + +### 3.2 SYNC PUBLISH & STREAM SUBSCRIBE + +- Start Request-Reply publisher to publish message (we have created the topic TEST-TOPIC-GRPC-RR by default, you can also create other topic to test) + +``` +Run the main method of org.apache.eventmesh.grpc.pub.eventmeshmessage.RequestReplyInstance +``` + +- Start stream subscriber + +``` +Run the main method of org.apache.eventmesh.grpc.sub.EventmeshAsyncSubscribe +``` + +### 3.3 PUBLISH BATCH MESSAGE + +- Start publisher to publish batch message (we have created the TEST-TOPIC-GRPC-ASYNC by default, you can also create other topic to test) + +``` +Run the main method of org.apache.eventmesh.grpc.pub.eventmeshmessage.BatchPublishInstance +``` + +More information about EventMesh-gRPC, please refer to [EventMesh gRPC](/docs/en/sdk-java/04-grpc.md) + +## 4 Run these demos by yourself + +Please refer to [EventMesh Store](/docs/en/instruction/01-store.md) and [EventMesh Runtime](/docs/en/instruction/02-runtime.md) to finish the necessary deployment before try our demo + +After finishing the deployment of store and runtime, you can run our demos in module `eventmesh-examples`: + +### TCP Sub + + ```shell + cd bin + sh tcp_eventmeshmessage_sub.sh + ``` + +### TCP Pub + + ```shell + cd bin + sh tcp_pub_eventmeshmessage.sh + ``` + +### TCP Sub Broadcast + + ```shell + cd bin + sh tcp_sub_eventmeshmessage_broadcast.sh + ``` + +### TCP Pub Broadcast + + ```shell + cd bin + sh tcp_pub_eventmeshmessage_broadcast.sh + ``` + +### HTTP Sub + + ```shell + cd bin + sh http_sub.sh + ``` + +### HTTP Pub + + ```shell + cd bin + sh http_pub_eventmeshmessage.sh + ``` + +You can review the log in the folder `/logs` diff --git a/docs/en/instruction/_category_.json b/docs/en/instruction/_category_.json new file mode 100644 index 0000000000..690c6eb204 --- /dev/null +++ b/docs/en/instruction/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 2, + "label": "Installation and Deployment", + "collapsed": false +} diff --git a/docs/en/introduction.md b/docs/en/introduction.md new file mode 100644 index 0000000000..991f81e10e --- /dev/null +++ b/docs/en/introduction.md @@ -0,0 +1,42 @@ +--- +sidebar_position: 0 +--- + +# Introduction to EventMesh + +[![CI status](https://img.shields.io/github/workflow/status/apache/incubator-eventmesh/Continuous%20Integration?logo=github&style=for-the-badge)](https://github.com/apache/incubator-eventmesh/actions/workflows/ci.yml) +[![CodeCov](https://img.shields.io/codecov/c/gh/apache/incubator-eventmesh/master?logo=codecov&style=for-the-badge)](https://codecov.io/gh/apache/incubator-eventmesh) +[![Code Quality: Java](https://img.shields.io/lgtm/grade/java/g/apache/incubator-eventmesh.svg?logo=lgtm&logoWidth=18&style=for-the-badge)](https://lgtm.com/projects/g/apache/incubator-eventmesh/context:java) +[![Total Alerts](https://img.shields.io/lgtm/alerts/g/apache/incubator-eventmesh.svg?logo=lgtm&logoWidth=18&style=for-the-badge)](https://lgtm.com/projects/g/apache/incubator-eventmesh/alerts/) +[![License](https://img.shields.io/github/license/apache/incubator-eventmesh?style=for-the-badge)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![GitHub Release](https://img.shields.io/github/v/release/apache/eventmesh?style=for-the-badge)](https://github.com/apache/incubator-eventmesh/releases) +[![Slack Status](https://img.shields.io/badge/slack-join_chat-blue.svg?logo=slack&style=for-the-badge)](https://join.slack.com/t/apacheeventmesh/shared_invite/zt-16y1n77va-q~JepYy3RqpkygDYmQaQbw) + +**Apache EventMesh (Incubating)** is a dynamic event-driven application runtime used to decouple the application and backend middleware layer, which supports a wide range of use cases that encompass complex multi-cloud, widely distributed topologies using diverse technology stacks. + +## Features + +- **Communication Protocol**: EventMesh could communicate with clients with TCP, HTTP, or gRPC. +- **CloudEvents**: EventMesh supports the [CloudEvents](https://cloudevents.io) specification as the format of the events. CloudEvents is a specification for describing event data in common formats to provide interoperability across services, platforms, and systems. +- **Schema Registry**: EventMesh implements a schema registry that receives and stores schemas from clients and provides an interface for other clients to retrieve schemas. +- **Observability**: EventMesh exposed a range of metrics, such as the average latency of the HTTP protocol and the number of delivered messages. The metrics could be collected and analyzed with Prometheus or OpenTelemetry. +- **Event Workflow Orchestration**: EventMesh Workflow could receive an event and decide which command to trigger next based on the workflow definitions and the current workflow state. The workflow definition could be written with the [Serverless Workflow](https://serverlessworkflow.io) DSL. + +## Components + +Apache EventMesh (Incubating) consists of multiple components that integrate different middlewares and messaging protocols to enhance the functionalities of the application runtime. + +- **eventmesh-runtime**: The middleware that transmits events between producers and consumers, which supports cloud-native apps and microservices. +- **eventmesh-sdk-java**: The Java SDK that supports HTTP, TCP, and [gRPC](https://grpc.io) protocols. +- **eventmesh-connector-plugin**: The collection of plugins that connects middlewares such as [Apache Kafka](https://kafka.apache.org), [Apache RocketMQ](https://rocketmq.apache.org), [Apache Pulsar](https://pulsar.apache.org/), and [Redis](https://redis.io). +- **eventmesh-registry-plugin**: The collection of plugins that integrate service registries such as [Nacos](https://nacos.io) and [etcd](https://etcd.io). +- **eventmesh-security-plugin**: The collection of plugins that implement security mechanisms, such as ACL (access control list), authentication, and authorization. +- **eventmesh-protocol-plugin**: The collection of plugins that implement messaging protocols, such as [CloudEvents](https://cloudevents.io) and [MQTT](https://mqtt.org). +- **eventmesh-admin**: The control plane that manages clients, topics, and subscriptions. + +## Contributors + +Each contributor has played an important role in promoting the robust development of Apache EventMesh (Incubating). We sincerely appreciate all contributors who have contributed code and documents. The following is the list of contributors in EventMesh-related repositories. + +- [apache/incubator-eventmesh](https://github.com/apache/incubator-eventmesh/graphs/contributors) +- [apache/incubator-eventmesh-site](https://github.com/apache/incubator-eventmesh-site/graphs/contributors) diff --git a/docs/en/roadmap.md b/docs/en/roadmap.md new file mode 100644 index 0000000000..e07a3a6645 --- /dev/null +++ b/docs/en/roadmap.md @@ -0,0 +1,50 @@ +--- +sidebar_position: 1 +--- + +# Development Roadmap + +The development roadmap of Apache EventMesh (Incubating) is an overview of the planned features and milestones involved in the next several releases. The recent features and bug fixes are documented in the [release notes](https://eventmesh.apache.org/events/release-notes/v1.4.0). The order of the features listed below doesn't correspond to their priorities. + +## List of Features and Milestones + +| Status | Description | Reference | +|-------------------------------------------|---------------------------------| --- | +| **Implemented in 1.0.0** | Support HTTP | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.0.0** | Support TCP | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.0.0** | Support Pub/Sub Event | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.1.1** | Provide Java SDK | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.1.1** | Support HTTPS | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.2.0** | Support RocketMQ as EventStore | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.2.0** | Support Heartbeat | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.3.0** | Integrate with OpenSchema | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.3.0** | Integrate with OpenTelemetry | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.3.0** | Support CloudEvents | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.4.0** | Support gRPC | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.5.0** | Provide Golang SDK | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.5.0** | Support Nacos Registry | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.5.0** | Support Mesh Bridge | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.5.0** | Support Federal Government | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.5.0** | Support Mesh Bridge | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.6.0** | Integrate with Consul | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.6.0** | Support Webhook | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.6.0** | Support etcd | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.7.0** | Support Knative Eventing Infrastructure | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/790), [GSoC '22](https://issues.apache.org/jira/browse/COMDEV-463) | +| **Implemented in 1.7.0** | Support Pravega as EventStore | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/270) | +| **Implemented in 1.7.0** | Support Kafka as EventStore | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/676) | +| **Implemented in 1.7.0** | Support Pulsar as EventStore | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/676) | +| **Implemented in 1.7.0** | Support CNCF Serverless Workflow| [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.7.0** | Support Redis | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.7.0** | Provide Rust SDK | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/815) | +| **Implemented in 1.7.0** | Support Zookeeper | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.7.0** | Support RabbitMQ as EventStore | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/1553) | +| **In Progress** | Provide Dashboard | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/700), [GSoC '22](https://issues.apache.org/jira/browse/COMDEV-465) +| **In Progress** | Support Filter Chain | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/664) | +| **In Progress** | Metadata consistency persistent | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/817) | +| Planned | Support Dledger | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| Planned | Provide NodeJS SDK | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| Planned | Provide PHP SDK | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/1193) | +| Planned | Transaction Event | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/697) | +| Planned | Event Query Language (EQL) | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/778) | +| Planned | WebAssembly Runtime | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/576) | + diff --git a/docs/en/sdk-java/02-http.md b/docs/en/sdk-java/02-http.md new file mode 100644 index 0000000000..bf2e5c6efa --- /dev/null +++ b/docs/en/sdk-java/02-http.md @@ -0,0 +1,115 @@ +# HTTP Protocol + +EventMesh SDK for Java implements the HTTP producer and consumer of asynchronous messages. Both the producer and consumer require an instance of `EventMeshHttpClientConfig` class that specifies the configuration of EventMesh HTTP client. The `liteEventMeshAddr`, `userName`, and `password` fields should match the `eventmesh.properties` file of EventMesh runtime. + +```java +import org.apache.eventmesh.client.http.conf.EventMeshHttpClientConfig; +import org.apache.eventmesh.common.utils.IPUtils; +import org.apache.eventmesh.common.utils.ThreadUtils; + +public class HTTP { + public static void main(String[] args) throws Exception { + EventMeshHttpClientConfig eventMeshClientConfig = EventMeshHttpClientConfig.builder() + .liteEventMeshAddr("localhost:10105") + .producerGroup("TEST_PRODUCER_GROUP") + .env("env") + .idc("idc") + .ip(IPUtils.getLocalAddress()) + .sys("1234") + .pid(String.valueOf(ThreadUtils.getPID())) + .userName("eventmesh") + .password("password") + .build(); + /* ... */ + } +} +``` + +## HTTP Consumer + +The `EventMeshHttpConsumer` class implements the `heartbeat`, `subscribe`, and `unsubscribe` methods. The `subscribe` method accepts a list of `SubscriptionItem` that defines the topics to be subscribed and a callback URL. + +```java +import org.apache.eventmesh.client.http.consumer.EventMeshHttpConsumer; +import org.apache.eventmesh.common.protocol.SubscriptionItem; +import org.apache.eventmesh.common.protocol.SubscriptionMode; +import org.apache.eventmesh.common.protocol.SubscriptionType; +import com.google.common.collect.Lists; + +public class HTTP { + final String url = "http://localhost:8080/callback"; + final List topicList = Lists.newArrayList( + new SubscriptionItem("eventmesh-async-topic", SubscriptionMode.CLUSTERING, SubscriptionType.ASYNC) + ); + + public static void main(String[] args) throws Exception { + /* ... */ + eventMeshHttpConsumer = new EventMeshHttpConsumer(eventMeshClientConfig); + eventMeshHttpConsumer.heartBeat(topicList, url); + eventMeshHttpConsumer.subscribe(topicList, url); + /* ... */ + eventMeshHttpConsumer.unsubscribe(topicList, url); + } +} +``` + +The EventMesh runtime will send a POST request that contains the message in the [CloudEvents format](https://github.com/cloudevents/spec) to the callback URL. The [`SubController.java` file](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-examples/src/main/java/org/apache/eventmesh/http/demo/sub/controller/SubController.java) implements a Spring Boot controller that receives and parses the callback messages. + +## HTTP Producer + +The `EventMeshHttpProducer` class implements the `publish` method. The `publish` method accepts the message to be published and an optional timeout value. The message should be an instance of either of these classes: + +- `org.apache.eventmesh.common.EventMeshMessage` +- `io.cloudevents.CloudEvent` +- `io.openmessaging.api.Message` + +```java +import org.apache.eventmesh.client.http.producer.EventMeshHttpProducer; +import org.apache.eventmesh.client.tcp.common.EventMeshCommon; +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.utils.JsonUtils; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; + +public class HTTP { + public static void main(String[] args) throws Exception { + /* ... */ + EventMeshHttpProducer eventMeshHttpProducer = new EventMeshHttpProducer(eventMeshClientConfig); + Map content = new HashMap<>(); + content.put("content", "testAsyncMessage"); + + CloudEvent event = CloudEventBuilder.v1() + .withId(UUID.randomUUID().toString()) + .withSubject("eventmesh-async-topic") + .withSource(URI.create("/")) + .withDataContentType("application/cloudevents+json") + .withType(EventMeshCommon.CLOUD_EVENTS_PROTOCOL_NAME) + .withData(JsonUtils.serialize(content).getBytes(StandardCharsets.UTF_8)) + .withExtension(Constants.EVENTMESH_MESSAGE_CONST_TTL, String.valueOf(4 * 1000)) + .build(); + eventMeshHttpProducer.publish(event); + } +} +``` + +## Using Curl Command + +You can also publish/subscribe event without eventmesh SDK. + +### Publish + +```shell +curl -H "Content-Type:application/json" -X POST -d '{"name": "admin", "pass":"12345678"}' http://127.0.0.1:10105/eventmesh/publish/TEST-TOPIC-HTTP-ASYNC +``` + +After you start the eventmesh runtime server, you can use the curl command publish the event to the specific topic with the HTTP POST method and the package body must be in JSON format. The publish url like (http://127.0.0.1:10105/eventmesh/publish/TEST-TOPIC-HTTP-ASYNC), and you will get the publish successful result. + +### Subscribe + +```shell +curl -H "Content-Type:application/json" -X POST -d '{"url": "http://127.0.0.1:8088/sub/test", "consumerGroup":"TEST-GROUP", "topic":[{"mode":"CLUSTERING","topic":"TEST-TOPIC-HTTP-ASYNC","type":"ASYNC"}]}' http://127.0.0.1:10105/eventmesh/subscribe/local +``` + +After you start the eventmesh runtime server, you can use the curl command to subscribe the specific topic list with the HTTP POST method, and the package body must be in JSON format. The subscribe url like (http://127.0.0.1:10105/eventmesh/subscribe/local), and you will get the subscribe successful result. You should pay attention to the `url` field in the package body, which means you need to set up an HTTP service at the specified URL, you can see the example in the `eventmesh-examples` module. + diff --git a/docs/en/sdk-java/03-tcp.md b/docs/en/sdk-java/03-tcp.md new file mode 100644 index 0000000000..1643a41dca --- /dev/null +++ b/docs/en/sdk-java/03-tcp.md @@ -0,0 +1,118 @@ +# TCP Protocol + +EventMesh SDK for Java implements the TCP producer and consumer of synchronous, asynchronous, and broadcast messages. Both the producer and consumer require an instance of `EventMeshTCPClientConfig` class that specifies the configuration of EventMesh TCP client. The `host` and `port` fields should match the `eventmesh.properties` file of EventMesh runtime. + +```java +import org.apache.eventmesh.client.tcp.conf.EventMeshTCPClientConfig; +import org.apache.eventmesh.client.tcp.common.ReceiveMsgHook; +import io.cloudevents.CloudEvent; + +public class AsyncSubscribe implements ReceiveMsgHook { + public static void main(String[] args) throws InterruptedException { + EventMeshTCPClientConfig eventMeshTcpClientConfig = EventMeshTCPClientConfig.builder() + .host(eventMeshIp) + .port(eventMeshTcpPort) + .userAgent(userAgent) + .build(); + /* ... */ + } +} +``` + +## TCP Consumer + +The consumer should implement the `ReceiveMsgHook` class, which is defined in [`ReceiveMsgHook.java`](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-sdk-java/src/main/java/org/apache/eventmesh/client/tcp/common/ReceiveMsgHook.java). + +```java +public interface ReceiveMsgHook { + Optional handle(ProtocolMessage msg); +} +``` + +The `EventMeshTCPClient` class implements the `subscribe` method. The `subscribe` method accepts the topic, the `SubscriptionMode`, and the `SubscriptionType`. The `handle` method will be invoked when the consumer receives a message from the topic it subscribes. If the `SubscriptionType` is `SYNC`, the return value of `handle` will be sent back to the producer. + +```java +import org.apache.eventmesh.client.tcp.EventMeshTCPClient; +import org.apache.eventmesh.client.tcp.EventMeshTCPClientFactory; +import org.apache.eventmesh.client.tcp.common.ReceiveMsgHook; +import org.apache.eventmesh.common.protocol.SubscriptionMode; +import org.apache.eventmesh.common.protocol.SubscriptionType; +import io.cloudevents.CloudEvent; + +public class TCPConsumer implements ReceiveMsgHook { + public static TCPConsumer handler = new TCPConsumer(); + private static EventMeshTCPClient client; + + public static void main(String[] args) throws Exception { + client = EventMeshTCPClientFactory.createEventMeshTCPClient( + eventMeshTcpClientConfig, + CloudEvent.class + ); + client.init(); + + client.subscribe( + "eventmesh-sync-topic", + SubscriptionMode.CLUSTERING, + SubscriptionType.SYNC + ); + + client.registerSubBusiHandler(handler); + client.listen(); + } + + @Override + public Optional handle(CloudEvent message) { + log.info("Messaged received: {}", message); + return Optional.of(message); + } +} +``` + +## TCP Producer + +### Asynchronous Producer + +The `EventMeshTCPClient` class implements the `publish` method. The `publish` method accepts the message to be published and an optional timeout value and returns the response message from the consumer. + +```java +/* ... */ +client = EventMeshTCPClientFactory.createEventMeshTCPClient(eventMeshTcpClientConfig, CloudEvent.class); +client.init(); + +CloudEvent event = CloudEventBuilder.v1() + .withId(UUID.randomUUID().toString()) + .withSubject(ExampleConstants.EVENTMESH_GRPC_ASYNC_TEST_TOPIC) + .withSource(URI.create("/")) + .withDataContentType(ExampleConstants.CLOUDEVENT_CONTENT_TYPE) + .withType(EventMeshCommon.CLOUD_EVENTS_PROTOCOL_NAME) + .withData(JsonUtils.serialize(content).getBytes(StandardCharsets.UTF_8)) + .withExtension(Constants.EVENTMESH_MESSAGE_CONST_TTL, String.valueOf(4 * 1000)) + .build(); +client.publish(event, 1000); +``` + +### Synchronous Producer + +The `EventMeshTCPClient` class implements the `rr` method. The `rr` method accepts the message to be published and an optional timeout value and returns the response message from the consumer. + +```java +/* ... */ +client = EventMeshTCPClientFactory.createEventMeshTCPClient(eventMeshTcpClientConfig, CloudEvent.class); +client.init(); + +CloudEvent event = CloudEventBuilder.v1() + .withId(UUID.randomUUID().toString()) + .withSubject(ExampleConstants.EVENTMESH_GRPC_ASYNC_TEST_TOPIC) + .withSource(URI.create("/")) + .withDataContentType(ExampleConstants.CLOUDEVENT_CONTENT_TYPE) + .withType(EventMeshCommon.CLOUD_EVENTS_PROTOCOL_NAME) + .withData(JsonUtils.serialize(content).getBytes(StandardCharsets.UTF_8)) + .withExtension(Constants.EVENTMESH_MESSAGE_CONST_TTL, String.valueOf(4 * 1000)) + .build(); + +Package response = client.rr(event, 1000); +CloudEvent replyEvent = EventFormatProvider + .getInstance() + .resolveFormat(JsonFormat.CONTENT_TYPE) + .deserialize(response.getBody().toString().getBytes(StandardCharsets.UTF_8)); +``` diff --git a/docs/en/sdk-java/04-grpc.md b/docs/en/sdk-java/04-grpc.md new file mode 100644 index 0000000000..81f03a8d83 --- /dev/null +++ b/docs/en/sdk-java/04-grpc.md @@ -0,0 +1,174 @@ +# gRPC Protocol + +EventMesh SDK for Java implements the gRPC producer and consumer of synchronous, asynchronous, and broadcast messages. Both the producer and consumer require an instance of `EventMeshGrpcClientConfig` class that specifies the configuration of EventMesh gRPC client. The `liteEventMeshAddr`, `userName`, and `password` fields should match the `eventmesh.properties` file of EventMesh runtime. + +```java +import org.apache.eventmesh.client.grpc.config.EventMeshGrpcClientConfig; +import org.apache.eventmesh.client.grpc.consumer.ReceiveMsgHook; +import io.cloudevents.CloudEvent; + +public class CloudEventsAsyncSubscribe implements ReceiveMsgHook { + public static void main(String[] args) throws InterruptedException { + EventMeshGrpcClientConfig eventMeshClientConfig = EventMeshGrpcClientConfig.builder() + .serverAddr("localhost") + .serverPort(10205) + .consumerGroup(ExampleConstants.DEFAULT_EVENTMESH_TEST_CONSUMER_GROUP) + .env("env").idc("idc") + .sys("1234").build(); + /* ... */ + } +} +``` + +## gRPC Consumer + +### Stream Consumer + +The EventMesh runtime sends the message from producers to the stream consumer as a series of event streams. The consumer should implement the `ReceiveMsgHook` class, which is defined in [`ReceiveMsgHook.java`](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-sdk-java/src/main/java/org/apache/eventmesh/client/grpc/consumer/ReceiveMsgHook.java). + +```java +public interface ReceiveMsgHook { + Optional handle(T msg) throws Throwable; + String getProtocolType(); +} +``` + +The `EventMeshGrpcConsumer` class implements the `registerListener`, `subscribe`, and `unsubscribe` methods. The `subscribe` method accepts a list of `SubscriptionItem` that defines the topics to be subscribed to. The `registerListener` accepts an instance of a class that implements the `ReceiveMsgHook`. The `handle` method will be invoked when the consumer receives a message from the topic it subscribes. If the `SubscriptionType` is `SYNC`, the return value of `handle` will be sent back to the producer. + +```java +import org.apache.eventmesh.client.grpc.consumer.EventMeshGrpcConsumer; +import org.apache.eventmesh.client.grpc.consumer.ReceiveMsgHook; +import org.apache.eventmesh.client.tcp.common.EventMeshCommon; +import org.apache.eventmesh.common.protocol.SubscriptionItem; +import org.apache.eventmesh.common.protocol.SubscriptionMode; +import org.apache.eventmesh.common.protocol.SubscriptionType; +import io.cloudevents.CloudEvent; + +public class CloudEventsAsyncSubscribe implements ReceiveMsgHook { + public static CloudEventsAsyncSubscribe handler = new CloudEventsAsyncSubscribe(); + public static void main(String[] args) throws InterruptedException { + /* ... */ + SubscriptionItem subscriptionItem = new SubscriptionItem( + "eventmesh-async-topic", + SubscriptionMode.CLUSTERING, + SubscriptionType.ASYNC + ); + EventMeshGrpcConsumer eventMeshGrpcConsumer = new EventMeshGrpcConsumer(eventMeshClientConfig); + + eventMeshGrpcConsumer.init(); + eventMeshGrpcConsumer.registerListener(handler); + eventMeshGrpcConsumer.subscribe(Collections.singletonList(subscriptionItem)); + /* ... */ + eventMeshGrpcConsumer.unsubscribe(Collections.singletonList(subscriptionItem)); + } + + @Override + public Optional handle(CloudEvent message) { + log.info("Messaged received: {}", message); + return Optional.empty(); + } + + @Override + public String getProtocolType() { + return EventMeshCommon.CLOUD_EVENTS_PROTOCOL_NAME; + } +} +``` + +### Webhook Consumer + +The `subscribe` method of the `EventMeshGrpcConsumer` class accepts a list of `SubscriptionItem` that defines the topics to be subscribed and an optional callback URL. If the callback URL is provided, the EventMesh runtime will send a POST request that contains the message in the [CloudEvents format](https://github.com/cloudevents/spec) to the callback URL. The [`SubController.java` file](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-examples/src/main/java/org/apache/eventmesh/grpc/sub/app/controller/SubController.java) implements a Spring Boot controller that receives and parses the callback messages. + +```java +import org.apache.eventmesh.client.grpc.consumer.EventMeshGrpcConsumer; +import org.apache.eventmesh.client.grpc.consumer.ReceiveMsgHook; +import org.apache.eventmesh.client.tcp.common.EventMeshCommon; +import org.apache.eventmesh.common.protocol.SubscriptionItem; +import org.apache.eventmesh.common.protocol.SubscriptionMode; +import org.apache.eventmesh.common.protocol.SubscriptionType; + +@Component +public class SubService implements InitializingBean { + final String url = "http://localhost:8080/callback"; + + public void afterPropertiesSet() throws Exception { + /* ... */ + eventMeshGrpcConsumer = new EventMeshGrpcConsumer(eventMeshClientConfig); + eventMeshGrpcConsumer.init(); + + SubscriptionItem subscriptionItem = new SubscriptionItem( + "eventmesh-async-topic", + SubscriptionMode.CLUSTERING, + SubscriptionType.ASYNC + ); + + eventMeshGrpcConsumer.subscribe(Collections.singletonList(subscriptionItem), url); + /* ... */ + eventMeshGrpcConsumer.unsubscribe(Collections.singletonList(subscriptionItem), url); + } +} +``` + +## gRPC Producer + +### Asynchronous Producer + +The `EventMeshGrpcProducer` class implements the `publish` method. The `publish` method accepts the message to be published and an optional timeout value. The message should be an instance of either of these classes: + +- `org.apache.eventmesh.common.EventMeshMessage` +- `io.cloudevents.CloudEvent` + +```java +/* ... */ +EventMeshGrpcProducer eventMeshGrpcProducer = new EventMeshGrpcProducer(eventMeshClientConfig); +eventMeshGrpcProducer.init(); + +Map content = new HashMap<>(); +content.put("content", "testAsyncMessage"); + +CloudEvent event = CloudEventBuilder.v1() + .withId(UUID.randomUUID().toString()) + .withSubject(ExampleConstants.EVENTMESH_GRPC_ASYNC_TEST_TOPIC) + .withSource(URI.create("/")) + .withDataContentType(ExampleConstants.CLOUDEVENT_CONTENT_TYPE) + .withType(EventMeshCommon.CLOUD_EVENTS_PROTOCOL_NAME) + .withData(JsonUtils.serialize(content).getBytes(StandardCharsets.UTF_8)) + .withExtension(Constants.EVENTMESH_MESSAGE_CONST_TTL, String.valueOf(4 * 1000)) + .build(); +eventMeshGrpcProducer.publish(event); +``` + +### Synchronous Producer + +The `EventMeshGrpcProducer` class implements the `requestReply` method. The `requestReply` method accepts the message to be published and an optional timeout value. The method returns the message returned from the consumer. The message should be an instance of either of these classes: + +- `org.apache.eventmesh.common.EventMeshMessage` +- `io.cloudevents.CloudEvent` + +### Batch Producer + +The `EventMeshGrpcProducer` class overloads the `publish` method, which accepts a list of messages to be published and an optional timeout value. The messages in the list should be an instance of either of these classes: + +- `org.apache.eventmesh.common.EventMeshMessage` +- `io.cloudevents.CloudEvent` + +```java +/* ... */ +List cloudEventList = new ArrayList<>(); +for (int i = 0; i < 5; i++) { + CloudEvent event = CloudEventBuilder.v1() + .withId(UUID.randomUUID().toString()) + .withSubject(ExampleConstants.EVENTMESH_GRPC_ASYNC_TEST_TOPIC) + .withSource(URI.create("/")) + .withDataContentType(ExampleConstants.CLOUDEVENT_CONTENT_TYPE) + .withType(EventMeshCommon.CLOUD_EVENTS_PROTOCOL_NAME) + .withData(JsonUtils.serialize(content).getBytes(StandardCharsets.UTF_8)) + .withExtension(Constants.EVENTMESH_MESSAGE_CONST_TTL, String.valueOf(4 * 1000)) + .build(); + + cloudEventList.add(event); +} + +eventMeshGrpcProducer.publish(cloudEventList); +/* ... */ +``` diff --git a/docs/en/sdk-java/_category_.json b/docs/en/sdk-java/_category_.json new file mode 100644 index 0000000000..e93d4cdd8a --- /dev/null +++ b/docs/en/sdk-java/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 3, + "label": "EventMesh SDK for Java", + "collapsed": false +} diff --git a/docs/en/sdk-java/intro.md b/docs/en/sdk-java/intro.md new file mode 100644 index 0000000000..42b9c41942 --- /dev/null +++ b/docs/en/sdk-java/intro.md @@ -0,0 +1,29 @@ +# Installation + +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.eventmesh/eventmesh-sdk-java/badge.svg?style=for-the-badge)](https://maven-badges.herokuapp.com/maven-central/org.apache.eventmesh/eventmesh-sdk-java) + +EventMesh SDK for Java is a collection of Java libraries to integrate EventMesh in a Java application. The SDK supports sending and receiving synchronous messages, asynchronous messages, and broadcast messages in TCP, HTTP, and gRPC protocols. The SDK implements EventMesh Message, CloudEvents, and OpenMessaging formats. The demo project is available in the [`eventmesh-example`](https://github.com/apache/incubator-eventmesh/tree/master/eventmesh-examples) module. + +## Gradle + +To install EventMesh SDK for Java with Gradle, declare `org.apache.eventmesh:eventmesh-sdk-java` as `implementation` in the dependencies block of the module's `build.gradle` file. + +```groovy +dependencies { + implementation 'org.apache.eventmesh:eventmesh-sdk-java:1.4.0' +} +``` + +## Maven + +To install EventMesh SDK for Java with Maven, declare `org.apache.eventmesh:eventmesh-sdk-java` as a dependency in the dependencies block of the project's `pom.xml` file. + +```xml + + + org.apache.eventmesh + eventmesh-sdk-java + 1.4.0 + + +``` diff --git a/docs/images/contact/wechat-assistant.jpg b/docs/images/contact/wechat-assistant.jpg new file mode 100644 index 0000000000..1ab02631fa Binary files /dev/null and b/docs/images/contact/wechat-assistant.jpg differ diff --git a/docs/images/contact/wechat-official.jpg b/docs/images/contact/wechat-official.jpg new file mode 100644 index 0000000000..deb5bfa29e Binary files /dev/null and b/docs/images/contact/wechat-official.jpg differ diff --git a/docs/images/contribute/checkstyle01.png b/docs/images/contribute/checkstyle01.png new file mode 100644 index 0000000000..84ceb3fab5 Binary files /dev/null and b/docs/images/contribute/checkstyle01.png differ diff --git a/docs/images/contribute/checkstyle02.png b/docs/images/contribute/checkstyle02.png new file mode 100644 index 0000000000..fb3a2e7764 Binary files /dev/null and b/docs/images/contribute/checkstyle02.png differ diff --git a/docs/images/contribute/checkstyle03.png b/docs/images/contribute/checkstyle03.png new file mode 100644 index 0000000000..e3cd16717a Binary files /dev/null and b/docs/images/contribute/checkstyle03.png differ diff --git a/docs/images/contribute/checkstyle04.png b/docs/images/contribute/checkstyle04.png new file mode 100644 index 0000000000..87723c9717 Binary files /dev/null and b/docs/images/contribute/checkstyle04.png differ diff --git a/docs/images/contribute/checkstyle05.png b/docs/images/contribute/checkstyle05.png new file mode 100644 index 0000000000..f8c6ec2812 Binary files /dev/null and b/docs/images/contribute/checkstyle05.png differ diff --git a/docs/images/contribute/checkstyle06.png b/docs/images/contribute/checkstyle06.png new file mode 100644 index 0000000000..cbfbf320a3 Binary files /dev/null and b/docs/images/contribute/checkstyle06.png differ diff --git a/docs/images/contribute/zh/contribute01.png b/docs/images/contribute/zh/contribute01.png new file mode 100644 index 0000000000..3e26d1c2e1 Binary files /dev/null and b/docs/images/contribute/zh/contribute01.png differ diff --git a/docs/images/contribute/zh/contribute02.png b/docs/images/contribute/zh/contribute02.png new file mode 100644 index 0000000000..0fdb57a96f Binary files /dev/null and b/docs/images/contribute/zh/contribute02.png differ diff --git a/docs/images/contribute/zh/contribute03.png b/docs/images/contribute/zh/contribute03.png new file mode 100644 index 0000000000..25feb79450 Binary files /dev/null and b/docs/images/contribute/zh/contribute03.png differ diff --git a/docs/images/contribute/zh/contribute04.png b/docs/images/contribute/zh/contribute04.png new file mode 100644 index 0000000000..fd7fe75938 Binary files /dev/null and b/docs/images/contribute/zh/contribute04.png differ diff --git a/docs/images/contribute/zh/contribute05.png b/docs/images/contribute/zh/contribute05.png new file mode 100644 index 0000000000..ea3f37840f Binary files /dev/null and b/docs/images/contribute/zh/contribute05.png differ diff --git a/docs/images/contribute/zh/contribute06.png b/docs/images/contribute/zh/contribute06.png new file mode 100644 index 0000000000..77a5711700 Binary files /dev/null and b/docs/images/contribute/zh/contribute06.png differ diff --git a/docs/images/contribute/zh/contribute07.png b/docs/images/contribute/zh/contribute07.png new file mode 100644 index 0000000000..1fe3218a39 Binary files /dev/null and b/docs/images/contribute/zh/contribute07.png differ diff --git a/docs/images/contribute/zh/contribute08.png b/docs/images/contribute/zh/contribute08.png new file mode 100644 index 0000000000..735e45b7c9 Binary files /dev/null and b/docs/images/contribute/zh/contribute08.png differ diff --git a/docs/images/contribute/zh/contribute09.png b/docs/images/contribute/zh/contribute09.png new file mode 100644 index 0000000000..76532380ca Binary files /dev/null and b/docs/images/contribute/zh/contribute09.png differ diff --git a/docs/images/contribute/zh/contribute10.png b/docs/images/contribute/zh/contribute10.png new file mode 100644 index 0000000000..446c788b8a Binary files /dev/null and b/docs/images/contribute/zh/contribute10.png differ diff --git a/docs/images/contribute/zh/contribute11.png b/docs/images/contribute/zh/contribute11.png new file mode 100644 index 0000000000..45677c587c Binary files /dev/null and b/docs/images/contribute/zh/contribute11.png differ diff --git a/docs/images/contribute/zh/contribute12.png b/docs/images/contribute/zh/contribute12.png new file mode 100644 index 0000000000..dee6656c7d Binary files /dev/null and b/docs/images/contribute/zh/contribute12.png differ diff --git a/docs/images/contribute/zh/contribute13.png b/docs/images/contribute/zh/contribute13.png new file mode 100644 index 0000000000..bacf42e15b Binary files /dev/null and b/docs/images/contribute/zh/contribute13.png differ diff --git a/docs/images/contribute/zh/contribute14.png b/docs/images/contribute/zh/contribute14.png new file mode 100644 index 0000000000..2abb07c82e Binary files /dev/null and b/docs/images/contribute/zh/contribute14.png differ diff --git a/docs/images/contribute/zh/contribute15.png b/docs/images/contribute/zh/contribute15.png new file mode 100644 index 0000000000..bb439af584 Binary files /dev/null and b/docs/images/contribute/zh/contribute15.png differ diff --git a/docs/images/contribute/zh/contribute16.png b/docs/images/contribute/zh/contribute16.png new file mode 100644 index 0000000000..cc9d653eb8 Binary files /dev/null and b/docs/images/contribute/zh/contribute16.png differ diff --git a/docs/images/contribute/zh/contribute17.png b/docs/images/contribute/zh/contribute17.png new file mode 100644 index 0000000000..85683c4832 Binary files /dev/null and b/docs/images/contribute/zh/contribute17.png differ diff --git a/docs/images/design-document/async-message.png b/docs/images/design-document/async-message.png new file mode 100644 index 0000000000..4ad6ac4e03 Binary files /dev/null and b/docs/images/design-document/async-message.png differ diff --git a/docs/images/design-document/broadcast-message.png b/docs/images/design-document/broadcast-message.png new file mode 100644 index 0000000000..7c3be10c30 Binary files /dev/null and b/docs/images/design-document/broadcast-message.png differ diff --git a/docs/images/design-document/cloudevents-pluggable-protocols.png b/docs/images/design-document/cloudevents-pluggable-protocols.png new file mode 100644 index 0000000000..5b8b858f10 Binary files /dev/null and b/docs/images/design-document/cloudevents-pluggable-protocols.png differ diff --git a/docs/images/design-document/event-bridge-detail.png b/docs/images/design-document/event-bridge-detail.png new file mode 100644 index 0000000000..95f815247b Binary files /dev/null and b/docs/images/design-document/event-bridge-detail.png differ diff --git a/docs/images/design-document/schema-registry-architecture.png b/docs/images/design-document/schema-registry-architecture.png new file mode 100644 index 0000000000..8de3fc3e05 Binary files /dev/null and b/docs/images/design-document/schema-registry-architecture.png differ diff --git a/docs/images/design-document/schema-registry-process.jpg b/docs/images/design-document/schema-registry-process.jpg new file mode 100644 index 0000000000..f914a81f0d Binary files /dev/null and b/docs/images/design-document/schema-registry-process.jpg differ diff --git a/docs/images/design-document/schema-registry-project-structure.png b/docs/images/design-document/schema-registry-project-structure.png new file mode 100644 index 0000000000..c12ac2b3e4 Binary files /dev/null and b/docs/images/design-document/schema-registry-project-structure.png differ diff --git a/docs/images/design-document/stream-architecture.png b/docs/images/design-document/stream-architecture.png new file mode 100644 index 0000000000..50d2ff9100 Binary files /dev/null and b/docs/images/design-document/stream-architecture.png differ diff --git a/docs/images/design-document/stream-component-interface.png b/docs/images/design-document/stream-component-interface.png new file mode 100644 index 0000000000..f8865f7d59 Binary files /dev/null and b/docs/images/design-document/stream-component-interface.png differ diff --git a/docs/images/design-document/stream-component-routes.png b/docs/images/design-document/stream-component-routes.png new file mode 100644 index 0000000000..98c8eb7509 Binary files /dev/null and b/docs/images/design-document/stream-component-routes.png differ diff --git a/docs/images/design-document/stream-event-driven-consumer.png b/docs/images/design-document/stream-event-driven-consumer.png new file mode 100644 index 0000000000..4be17f4746 Binary files /dev/null and b/docs/images/design-document/stream-event-driven-consumer.png differ diff --git a/docs/images/design-document/stream-sync-producer.png b/docs/images/design-document/stream-sync-producer.png new file mode 100644 index 0000000000..bb8771cfe5 Binary files /dev/null and b/docs/images/design-document/stream-sync-producer.png differ diff --git a/docs/images/design-document/sync-message.png b/docs/images/design-document/sync-message.png new file mode 100644 index 0000000000..b1c462fa51 Binary files /dev/null and b/docs/images/design-document/sync-message.png differ diff --git a/docs/images/design-document/tcp-protocol.png b/docs/images/design-document/tcp-protocol.png new file mode 100644 index 0000000000..d3c1249d53 Binary files /dev/null and b/docs/images/design-document/tcp-protocol.png differ diff --git a/docs/images/design-document/webhook/webhook-github-add.png b/docs/images/design-document/webhook/webhook-github-add.png new file mode 100644 index 0000000000..55e19cb614 Binary files /dev/null and b/docs/images/design-document/webhook/webhook-github-add.png differ diff --git a/docs/images/design-document/webhook/webhook-github-info.png b/docs/images/design-document/webhook/webhook-github-info.png new file mode 100644 index 0000000000..978b64eb90 Binary files /dev/null and b/docs/images/design-document/webhook/webhook-github-info.png differ diff --git a/docs/images/design-document/webhook/webhook-github-setting.png b/docs/images/design-document/webhook/webhook-github-setting.png new file mode 100644 index 0000000000..fa151313ce Binary files /dev/null and b/docs/images/design-document/webhook/webhook-github-setting.png differ diff --git a/docs/images/design-document/webhook/webhook-github-webhooks.png b/docs/images/design-document/webhook/webhook-github-webhooks.png new file mode 100644 index 0000000000..978b64eb90 Binary files /dev/null and b/docs/images/design-document/webhook/webhook-github-webhooks.png differ diff --git a/docs/images/design-document/workflow-architecture.jpg b/docs/images/design-document/workflow-architecture.jpg new file mode 100644 index 0000000000..1bbb691c07 Binary files /dev/null and b/docs/images/design-document/workflow-architecture.jpg differ diff --git a/docs/images/design-document/workflow-diagram.png b/docs/images/design-document/workflow-diagram.png new file mode 100644 index 0000000000..0c2c825dcc Binary files /dev/null and b/docs/images/design-document/workflow-diagram.png differ diff --git a/docs/images/design-document/workflow-use-case.jpg b/docs/images/design-document/workflow-use-case.jpg new file mode 100644 index 0000000000..124e7ec233 Binary files /dev/null and b/docs/images/design-document/workflow-use-case.jpg differ diff --git a/docs/images/eventmesh-arch.png b/docs/images/eventmesh-arch.png deleted file mode 100644 index 55ce5ddbb6..0000000000 Binary files a/docs/images/eventmesh-arch.png and /dev/null differ diff --git a/docs/images/eventmesh-architecture-2.png b/docs/images/eventmesh-architecture-2.png new file mode 100644 index 0000000000..7accab6157 Binary files /dev/null and b/docs/images/eventmesh-architecture-2.png differ diff --git a/docs/images/eventmesh-architecture.png b/docs/images/eventmesh-architecture.png new file mode 100644 index 0000000000..5405afc593 Binary files /dev/null and b/docs/images/eventmesh-architecture.png differ diff --git a/docs/images/eventmesh-bridge.png b/docs/images/eventmesh-bridge.png new file mode 100644 index 0000000000..b8d1220f20 Binary files /dev/null and b/docs/images/eventmesh-bridge.png differ diff --git a/docs/images/eventmesh-define.png b/docs/images/eventmesh-define.png deleted file mode 100644 index f0c62d1b4d..0000000000 Binary files a/docs/images/eventmesh-define.png and /dev/null differ diff --git a/docs/images/eventmesh-orchestration.png b/docs/images/eventmesh-orchestration.png new file mode 100644 index 0000000000..40b28208a5 Binary files /dev/null and b/docs/images/eventmesh-orchestration.png differ diff --git a/docs/images/favicon.ico b/docs/images/favicon.ico new file mode 100644 index 0000000000..b6b6c2c6ef Binary files /dev/null and b/docs/images/favicon.ico differ diff --git a/docs/images/features/RR-call-p1.png b/docs/images/features/RR-call-p1.png deleted file mode 100644 index 2232df3e1f..0000000000 Binary files a/docs/images/features/RR-call-p1.png and /dev/null differ diff --git a/docs/images/features/a-distributing-architecture-in-financial-EN.png b/docs/images/features/a-distributing-architecture-in-financial-EN.png deleted file mode 100644 index 7e7b3d7f8d..0000000000 Binary files a/docs/images/features/a-distributing-architecture-in-financial-EN.png and /dev/null differ diff --git a/docs/images/features/a-distributing-architecture-in-financial.png b/docs/images/features/a-distributing-architecture-in-financial.png deleted file mode 100644 index d7eeb9d246..0000000000 Binary files a/docs/images/features/a-distributing-architecture-in-financial.png and /dev/null differ diff --git a/docs/images/features/adjust-queue-expand-p1.png b/docs/images/features/adjust-queue-expand-p1.png deleted file mode 100644 index 2660f3139b..0000000000 Binary files a/docs/images/features/adjust-queue-expand-p1.png and /dev/null differ diff --git a/docs/images/features/adjust-queue-shrink-p1.png b/docs/images/features/adjust-queue-shrink-p1.png deleted file mode 100644 index e4dc500f96..0000000000 Binary files a/docs/images/features/adjust-queue-shrink-p1.png and /dev/null differ diff --git a/docs/images/features/architecture-p1.png b/docs/images/features/architecture-p1.png deleted file mode 100644 index cda0b0433a..0000000000 Binary files a/docs/images/features/architecture-p1.png and /dev/null differ diff --git a/docs/images/features/broadcast.png b/docs/images/features/broadcast.png deleted file mode 100644 index 2cf528d988..0000000000 Binary files a/docs/images/features/broadcast.png and /dev/null differ diff --git a/docs/images/features/circuit-break-p1.png b/docs/images/features/circuit-break-p1.png deleted file mode 100644 index b3f55f75cd..0000000000 Binary files a/docs/images/features/circuit-break-p1.png and /dev/null differ diff --git a/docs/images/features/dark-launch-p1.png b/docs/images/features/dark-launch-p1.png deleted file mode 100644 index 08c04430b6..0000000000 Binary files a/docs/images/features/dark-launch-p1.png and /dev/null differ diff --git a/docs/images/features/invoke_nearby-p1.png b/docs/images/features/invoke_nearby-p1.png deleted file mode 100644 index 2aa0afe961..0000000000 Binary files a/docs/images/features/invoke_nearby-p1.png and /dev/null differ diff --git a/docs/images/features/multicast.png b/docs/images/features/multicast.png deleted file mode 100644 index 9643044457..0000000000 Binary files a/docs/images/features/multicast.png and /dev/null differ diff --git a/docs/images/features/subscribe-nearby-p1.png b/docs/images/features/subscribe-nearby-p1.png deleted file mode 100644 index d3a141922f..0000000000 Binary files a/docs/images/features/subscribe-nearby-p1.png and /dev/null differ diff --git a/docs/images/features/tongchengduohuo-p1.png b/docs/images/features/tongchengduohuo-p1.png deleted file mode 100644 index 663186ae1c..0000000000 Binary files a/docs/images/features/tongchengduohuo-p1.png and /dev/null differ diff --git a/docs/images/features/unicast.png b/docs/images/features/unicast.png deleted file mode 100644 index 1be62694eb..0000000000 Binary files a/docs/images/features/unicast.png and /dev/null differ diff --git a/docs/images/incubator-logo.png b/docs/images/incubator-logo.png new file mode 100644 index 0000000000..759252f001 Binary files /dev/null and b/docs/images/incubator-logo.png differ diff --git a/docs/images/logo.png b/docs/images/logo.png new file mode 100644 index 0000000000..e8545510d1 Binary files /dev/null and b/docs/images/logo.png differ diff --git a/docs/images/qqgroup-crcode.png b/docs/images/qqgroup-crcode.png deleted file mode 100644 index 10ca3c2aeb..0000000000 Binary files a/docs/images/qqgroup-crcode.png and /dev/null differ diff --git a/docs/images/wechat_helper.png b/docs/images/wechat_helper.png deleted file mode 100644 index 35c21a3f98..0000000000 Binary files a/docs/images/wechat_helper.png and /dev/null differ diff --git a/docs/zh/contribute/01-release.md b/docs/zh/contribute/01-release.md new file mode 100644 index 0000000000..0810a75772 --- /dev/null +++ b/docs/zh/contribute/01-release.md @@ -0,0 +1,731 @@ +# Release Creation Process + +:::caution +The documentation of Release Creation Process is WIP (Work-in-Progress). +::: + +## 理解 Apache 发布的内容和流程 + +Source Release 是 Apache 关注的重点,也是发布的必须内容;而 Binary Release 是可选项, + +请参考以下链接,找到更多关于 ASF 的发布指南: + +- [Apache Release Guide](http://www.apache.org/dev/release-publishing) +- [Apache Release Policy](http://www.apache.org/dev/release.html) +- [Maven Release Info](http://www.apache.org/dev/publishing-maven-artifacts.html) + + +## 本地构建环境准备 + +主要包括签名工具、Maven 仓库认证相关准备 + +### 1.安装GPG + +在[GnuPG官网](https://www.gnupg.org/download/index.html)下载安装包。GnuPG的1.x版本和2.x版本的命令有细微差别,下列说明以**GnuPG-2.x**版本为例 + +```sh +$ gpg --version #检查版本,应该为2.x +``` + +### 2.用gpg生成key + +根据提示,生成 key + +> 注意:请使用Apache邮箱生成GPG的Key + +```shell +$ gpg --full-gen-key +gpg (GnuPG) 2.0.12; Copyright (C) 2009 Free Software Foundation, Inc. +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + +Please select what kind of key you want: + (1) RSA and RSA (default) + (2) DSA and Elgamal + (3) DSA (sign only) + (4) RSA (sign only) +Your selection? 1 +RSA keys may be between 1024 and 4096 bits long. +What keysize do you want? (2048) 4096 +Requested keysize is 4096 bits +Please specify how long the key should be valid. + 0 = key does not expire + = key expires in n days + w = key expires in n weeks + m = key expires in n months + y = key expires in n years +Key is valid for? (0) +Key does not expire at all +Is this correct? (y/N) y + +GnuPG needs to construct a user ID to identify your key. + +Real name: ${输入用户名} +Email address: ${邮箱地址} +Comment: CODE SIGNING KEY +You selected this USER-ID: + "${输入用户名} (CODE SIGNING KEY) <${邮箱地址}>" + +Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O +You need a Passphrase to protect your secret key. # 填入密码,以后打包过程中会经常用到 +``` + +### 3.查看 key + +```shell +$ gpg --list-keys +pub rsa4096/579C25F5 2021-04-26 # 579C25F5就是key id +uid [ultimate] ${输入用户名} <${邮箱地址}> +sub rsa4096 2021-04-26 + +# 通过key id发送public key到keyserver +$ gpg --keyserver pgpkeys.mit.edu --send-key 579C25F5 +# 其中,pgpkeys.mit.edu为随意挑选的keyserver,keyserver列表为:https://sks-keyservers.net/status/,相互之间是自动同步的,选任意一个都可以。 +$ gpg --keyserver hkp://pgpkeys.mit.edu --recv-keys 579C25F5 # 验证是否同步到公网,网络不好可能需多试几次 +``` + +**注:如果有多个 public key,设置默认 key。**修改`~/.gnupg/gpg.conf` + +```sh +# If you have more than 1 secret key in your keyring, you may want to +# uncomment the following option and set your preferred keyid. +default-key 28681CB1 +``` + +**如果有多个 public key, 也可以删除无用的 key:** + +```shell +$ gpg --delete-secret-keys 29BBC3CB # 先删除私钥,指明key id +gpg (GnuPG) 2.2.27; Copyright (C) 2021 g10 Code GmbH +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + +sec rsa4096/EE8DAE7D29BBC3CB 2021-04-27 mikexue + +Delete this key from the keyring? (y/N) y +This is a secret key! - really delete? (y/N) y +``` + +```shell +$ gpg --delete-keys 29BBC3CB # 删除公钥,指明key id +gpg (GnuPG) 2.2.27; Copyright (C) 2021 g10 Code GmbH +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + + +pub rsa4096/EE8DAE7D29BBC3CB 2021-04-27 mikexue + +Delete this key from the keyring? (y/N) y +``` + +由于公钥服务器没有检查机制,任何人都可以用你的名义上传公钥,所以没有办法保证服务器上的公钥的可靠性。 通常,你可以在网站上公布一个公钥指纹,让其他人核对下载到的公钥是否为真。 + +```shell +# fingerprint参数生成公钥指纹: +$gpg --fingerprint mikexue +pub rsa4096 2021-04-26 [SCA] + F84A 0041 D70B 37AF 9C7B F0B3 39F4 29D7 579C 25F5 +uid [ultimate] mikexue +sub rsa4096 2021-04-26 [E] +``` + +登录 [https://id.apache.org](https://id.apache.org/), 将上面的 fingerprint (即 F84A 0041 D70B 37AF 9C7B F0B3 39F4 29D7 579C 25F5) 粘贴到自己的用户信息中 OpenPGP Public Key Primary Fingerprint + + + +## 发布Apache Maven仓库 + +> 注:EventMesh使用Gradle构建,需修改gradle相关配置 + +### 1.导出私钥文件 + +```shell +$ gpg --export-secret-keys -o secring.gpg #私钥文件妥善保管,后面配置需要 +``` + +### 2.准备分支 + +从主干分支拉取新分支作为发布分支,如现在要发布$`{release_version}`版本,则从develop分支拉出新分支`${release_version}-release`,此后`${release_version}` Release Candidates涉及的修改及打标签等都在`${release_version}-release`分支进行,最终发布完成后合入主干分支。 + +### 3.更新版本说明 + +更新官网项目的如下文件,并提交至master分支: + +https://github.com/apache/incubator-eventmesh-site/tree/master/events/release-notes + +### 4.配置根项目下gradle.properties文件 + +```shell +group=org.apache.eventmesh +version=1.2.0-release +#40位公钥的最后8位 +signing.keyId=579C25F5 +#生成密钥时填的passphrase +signing.password= +#导出的私钥文件secring.gpg路径 +signing.secretKeyRingFile=../secring.gpg +#apache 账号 +apacheUserName= +#apache 密码 +apachePassWord= +``` + +### 5.检查子模块下gradle.properties文件 + +```shell +group=org.apache.eventmesh +version=${release_version} +``` + +### 6.检查并配置根项目下build.gradle文件 + +```shell +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + artifact packageSources + artifact packageJavadoc + versionMapping { + usage('java-api') { + fromResolutionOf('runtimeClasspath') + } + usage('java-runtime') { + fromResolutionResult() + } + } + pom { + name = 'EventMesh' + description = 'Apache EventMesh' + url = 'https://github.com/apache/incubator-eventmesh' + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + developers { + developer { + id = 'Apache EventMesh(incubating)' + name = 'Apache EventMesh(incubating) of ASF' + url = 'https://eventmesh.apache.org/' + } + } + scm { + connection = 'scm:git:git@github.com:apache/incubator-eventmesh.git' + developerConnection = 'scm:git:git@github.com:apache/incubator-eventmesh.git' + url = 'https://github.com/apache/incubator-eventmesh' + } + } + } + } + repositories { + maven { + def releasesRepoUrl = 'https://repository.apache.org/service/local/staging/deploy/maven2/' + def snapshotsRepoUrl = 'https://repository.apache.org/content/repositories/snapshots/' + url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl + credentials { + username apacheUserName + password apachePassWord + } + + } + } +} + +signing { + sign publishing.publications.mavenJava +} +``` + +### 7.上传发布包 + +执行如下命令,需要对jar、源码包、doc和pom等文件签名加密 + +```shell +$ gradle signMavenJavaPublication publish +``` + +上述命令执行成功后,待发布版本会自动上传到Apache的临时筹备仓库(staging repository)。所有被deploy到远程[maven仓库](http://repository.apache.org/)的Artifacts都会处于staging状态,访问https://repository.apache.org/#stagingRepositories, 使用Apache的LDAP账户登录后,就会看到上传的版本,`Repository`列的内容即为${STAGING.REPOSITORY}。 点击`Close`来告诉Nexus这个构建已经完成,只有这样该版本才是可用的。 如果电子签名等出现问题,`Close`会失败,可以通过`Activity`查看失败信息。 + + + +## 发布Apache SVN仓库 + +### 1.准备svn本机环境(Apache使用svn托管项目的发布内容) + +### 2.checkout到本地目录 + +```shell +$ svn checkout https://dist.apache.org/repos/dist/dev/incubator/eventmesh/ +# 假定本地目录为 ~/apache/eventmesh +``` + +### 3.添加gpg公钥 + +添加public key到[KEYS](https://dist.apache.org/repos/dist/dev/incubator/eventmesh/KEYS)文件并提交到SVN仓库(第一次做发布的人需要做这个操作,具体操作参考KEYS文件里的说明)。KEYS主要是让参与投票的人在本地导入,用来校验sign的正确性 + +Windows + +```sh +$ gpg --list-sigs | out-file -append KEYS -encoding utf8 +$ gpg --armor --export | out-file -append KEYS -encoding utf8 +``` + +> Mac OS/Linux + +```sh +$ (gpg --list-sigs && gpg --armor --export ) >> KEYS +``` + +### 4.添加待发布内容到SVN目录 + +```shell +$ cd ~/apache/eventmesh # eventmesh svn根目录 +$ mkdir ${release_version}-${rc_version} +``` + +#### 4.1 创建tag + +在`${release_version}-release`分支上创建tag,需带有rc版本,为预发布版本 + +```shell +$ git tag -a v{$release_version}-{$rc_version} -m "Tagging the ${release_version} first Release Candidate (Candidates start at zero)" +$ git push origin --tags +``` + +#### 4.2 打包源码 + +检查项目源码命名,将源码命名为`apache-eventmesh-${release_version}-incubating-src`,将源码打包为tar.gz格式 + +```shell +$ tar -czvf apache-eventmesh-${release_version}-incubating-source.tar.gz apache-eventmesh-${release_version}-incubating-src +``` + +#### 4.3 打包二进制 + +> 编译上一步打包的源码 + +检查编译后的文件命名,将二进制文件命名为`apache-eventmesh-${release_version}-incubating` + +> 注:需将源码根目录下的`NOTICE`文件,`DISCLAIMER-WIP`文件以及`tools/third-party-licenses`目录下的`LICENSE`文件拷贝到二进制的包中 + +```shell +$ gradle clean jar dist && gradle installPlugin && gradle tar -x test +$ tar -czvf apache-eventmesh-${release_version}-incubating-bin.tar.gz apache-eventmesh-${release_version}-incubating +``` + +压缩source包、bin包,并将相关的压缩包拷贝到svn本地仓库下`/apache/eventmesh/${release_version}-${rc_version}` + +### 5.生成签名/sha512文件 + +> 针对源码包与二进制包生成签名/sha512文件 + +```shell +$ for i in *.tar.gz; do echo $i; gpg --print-md SHA512 $i > $i.sha512 ; done #计算sha512 +$ for i in *.tar.gz; do echo $i; gpg --armor --output $i.asc --detach-sig $i ; done #计算签名 +``` + +### 6.提交到Apache svn + +```shell +$ cd ~/apache/eventmesh # eventmesh svn根目录 +$ svn status +$ svn commit -m 'prepare for ${release_version}-${rc_version}' +``` + + + +## 验证Release Candidates + +详细检查列表请参考官方的[check list](https://cwiki.apache.org/confluence/display/INCUBATOR/Incubator+Release+Checklist) + +从以下地址下载要发布的Release Candidates到本地环境: + +```shell +https://dist.apache.org/repos/dist/dev/incubator/eventmesh/${release_version}-${rc_version}/ +``` + +然后开始验证环节,验证包含但不限于以下内容和形式 + +### 1.检查签名和hash等信息 + +> 由于操作系统不同,检查的命令或有差异,具体可参考[官方检查步骤](https://www.apache.org/info/verification.html) + +#### 1.1检查sha512哈希 + +> Mac OS/Linux + +```shell +$ shasum -a apache-eventmesh-${release_version}-incubating-source.tar.gz +#并将输出内容与 apache-eventmesh-${release_version}-${rc_version}-incubating-source.tar.gz.sha512文件内容作对比 +$ shasum -a apache-eventmesh-${release_version}-incubating-bin.tar.gz +#并将输出内容与 apache-eventmesh-${release_version}-${rc_version}-incubating-bin.tar.gz.sha512文件内容作对比 +``` + +> Windows + +```shell +$ certUtil -hashfile apache-eventmesh-${release_version}-incubating-source.tar.gz SHA512 +#并将输出内容与 apache-eventmesh-${release_version}-${rc_version}-incubating-source.tar.gz.sha512文件内容作对比 +$ certUtil -hashfile apache-eventmesh-${release_version}-incubating-bin.tar.gz SHA512 +#并将输出内容与 apache-eventmesh-${release_version}-${rc_version}-incubating-bin.tar.gz.sha512文件内容作对比 +``` + +#### 1.2检查gpg签名 + +首先导入发布人公钥。从svn仓库导入KEYS到本地环境。(发布版本的人不需要再导入,帮助做验证的人需要导入,用户名填发版人的即可) + +```shell +$ curl https://dist.apache.org/repos/dist/dev/incubator/eventmesh/KEYS >> KEYS +$ gpg --import KEYS +$ gpg --edit-key "${发布人的gpg用户名}" + > trust + +Please decide how far you trust this user to correctly verify other users' keys +(by looking at passports, checking fingerprints from different sources, etc.) + + 1 = I don't know or won't say + 2 = I do NOT trust + 3 = I trust marginally + 4 = I trust fully + 5 = I trust ultimately + m = back to the main menu + +Your decision? 5 + + > save +``` + +然后使用如下命令检查签名 + +```shell +$ gpg --verify apache-eventmesh-${release_version}-incubating-source.tar.gz.asc apache-eventmesh-${release_version}-incubating-source-tar.gz +$ gpg --verify apache-eventmesh-${release_version}-incubating-bin.tar.gz.asc apache-eventmesh-${release_version}-incubating-bin.tar.gz +``` + +### 2.检查源码包的文件内容 + +解压缩`apache-eventmesh-${release_version}-incubating-source-tar.gz`,进行如下检查: + +- 检查源码包是否包含由于包含不必要文件,致使tar包过于庞大 +- 文件夹包含单词`incubating` +- 存在`LICENSE`和`NOTICE`文件 +- 存在`DISCLAIMER`文件 +- `NOTICE`文件中的年份正确 +- 只存在文本文件,不存在二进制文件 +- 所有文件的开头都有ASF许可证 +- 能够正确编译,单元测试可以通过 (./gradle build) (目前支持JAVA 8/gradle 7.0/idea 2021.1.1及以上) +- 检查是否有多余文件或文件夹,例如空文件夹等 + +### 3.检查二进制包的文件内容 + +- 文件夹包含单词`incubating` +- 存在`LICENSE`和`NOTICE`文件 +- 存在`DISCLAIMER`文件 +- `NOTICE`文件中的年份正确 +- 所有文本文件开头都有ASF许可证 +- 检查第三方依赖许可证: + - 第三方依赖的许可证兼容 + - 所有第三方依赖的许可证都在`LICENSE`文件中声名 + - 依赖许可证的完整版全部在`license`目录 + - 如果依赖的是Apache许可证并且存在`NOTICE`文件,那么这些`NOTICE`文件也需要加入到版本的`NOTICE`文件中 + +你可以参考此文章:[ASF第三方许可证策](https://apache.org/legal/resolved.html) + +## 发起投票 + +> EventMesh 仍在孵化阶段,需要进行两次投票 + +- EventMesh社区投票,发送邮件至:`dev@eventmesh.apache.org` +- incubator社区投票,发送邮件至:`general@incubator.apache.org` EventMesh毕业后,只需要在EventMesh社区投票 + +### 1.EventMesh社区投票阶段 + +1. EventMesh社区投票,发起投票邮件到`dev@eventmesh.apache.org`。PMC需要先按照文档检查版本的正确性,然后再进行投票。 经过至少72小时并统计到3个`+1 PMC member`票后,即可进入下一阶段的投票。 +2. 宣布投票结果,发起投票结果邮件到`dev@eventmesh.apache.org`。 + +### 2.EventMesh社区投票模板 + +标题: + +``` +[VOTE] Release Apache EventMesh (incubating) ${release_version} ${rc_version} +``` + +正文: + +``` +Hello EventMesh Community, + + This is a call for vote to release Apache EventMesh (incubating) version ${release_version}-${rc_version}. + + Release notes: + https://github.com/apache/incubator-eventmesh/releases/tag/v${release_version}-${rc_version} + + The release candidates: + https://dist.apache.org/repos/dist/dev/incubator/eventmesh/${release_version}-${rc_version}/ + + Maven artifacts are available in a staging repository at: + https://repository.apache.org/content/repositories/orgapacheeventmesh-{staging-id} + + Git tag for the release: + https://github.com/apache/incubator-eventmesh/tree/v${release_version}-${rc_version} + + Keys to verify the Release Candidate: + https://downloads.apache.org/incubator/eventmesh/KEYS + + Hash for the release tag: + #hashCode of this release tag + + GPG user ID: + ${YOUR.GPG.USER.ID} + + The vote will be open for at least 72 hours or until necessary number of votes are reached. + + Please vote accordingly: + + [ ] +1 approve + + [ ] +0 no opinion + + [ ] -1 disapprove with the reason + + Checklist for reference: + + [ ] Download links are valid. + + [ ] Checksums and PGP signatures are valid. + + [ ] Source code distributions have correct names matching the current release. + + [ ] LICENSE and NOTICE files are correct for each EventMesh repo. + + [ ] All files have license headers if necessary. + + [ ] No compiled archives bundled in source archive. + + More detail checklist please refer: + https://cwiki.apache.org/confluence/display/INCUBATOR/Incubator+Release+Checklist + +Thanks, +Your EventMesh Release Manager +``` + +### 3.宣布投票结果模板 + +标题: + +``` +[RESULT][VOTE] Release Apache EventMesh (incubating) ${release_version} ${rc_version} +``` + +正文: + +``` +Hello Apache EventMesh PPMC and Community, + + The vote closes now as 72hr have passed. The vote PASSES with + + xx (+1 non-binding) votes from the PPMC, + xx (+1 binding) votes from the IPMC, + xx (+1 non-binding) votes from the rest of the developer community, + and no further 0 or -1 votes. + + The vote thread: {vote_mail_address} + + I will now bring the vote to general@incubator.apache.org to get approval by the IPMC. + If this vote passes also, the release is accepted and will be published. + +Thank you for your support. +Your EventMesh Release Manager +``` + +### 4.Incubator社区投票阶段 + +1. Incubator社区投票,发起投票邮件到`general@incubator.apache.org`,需3个 `+1 IPMC Member`投票,方可进入下一阶段。 +2. 宣布投票结果,发起投票结果邮件到`general@incubator.apache.org` 并抄送至`dev@eventmesh.apache.org`。 + +### 5.Incubator社区投票模板 + +标题: + +``` +[VOTE] Release Apache EventMesh (incubating) ${release_version} ${rc_version} +``` + +内容: + +``` +Hello Incubator Community, + + This is a call for a vote to release Apache EventMesh(Incubating) version ${release_version} ${rc_version} + + The Apache EventMesh community has voted on and approved a proposal to release + Apache EventMesh(Incubating) version ${release_version} ${rc_version} + + We now kindly request the Incubator PMC members review and vote on this + incubator release. + + EventMesh community vote thread: + • [投票链接] + + Vote result thread: + • [投票结果链接] + + The release candidate: + •https://dist.apache.org/repos/dist/dev/incubator/eventmesh/${release_version}-${rc_version}/ + + Git tag for the release: + • https://github.com/apache/incubator-eventmesh/tree/${release_version}-${rc_version} + Release notes: + • https://github.com/apache/incubator-eventmesh/releases/tag/${release_version}-${rc_version} + + The artifacts signed with PGP key [填写你个人的KEY], corresponding to [填写你个人的邮箱], that can be found in keys file: + • https://downloads.apache.org/incubator/eventmesh/KEYS + + The vote will be open for at least 72 hours or until necessary number of votes are reached. + + Please vote accordingly: + + [ ] +1 approve + [ ] +0 no opinion + [ ] -1 disapprove with the reason + +Thanks, +On behalf of Apache EventMesh(Incubating) community +``` + +### 6.宣布投票结果模板 + +标题: + +``` +[RESULT][VOTE] Release Apache EventMesh (incubating) ${release_version} ${rc_version} +``` + +内容: + +``` +Hi all, + + Thanks for reviewing and voting for Apache EventMesh(Incubating) version ${release_version} ${rc_version} release, I am happy to announce the release voting has passed with [投票结果数] binding votes, no +0 or -1 votes. + + Binding votes are from IPMC + - xxx + - xxx + - xxx + + Non-binding votes: + +1 xxx + +0 xxx + -1 xxx + + The voting thread is: + • [投票结果链接] + + Many thanks for all our mentors helping us with the release procedure, and all IPMC helped us to review and vote for Apache EventMesh(Incubating) release. I will be working on publishing the artifacts soon. + +Thanks, +On behalf of Apache EventMesh(Incubating) community +``` + +## 正式发布 + +### 1.合并分支 + +合并`${release_version}-release`分支的改动到`master`分支,合并完成后删除`release`分支 + +```shell +$ git checkout master +$ git merge origin/${release_version}-release +$ git pull +$ git push origin master +$ git push --delete origin ${release_version}-release +$ git branch -d ${release_version}-release +``` + +### 2.迁移源码与二进制包 + +将源码和二进制包从svn的`dev`目录移动到`release`目录 + +```shell +$ svn mv https://dist.apache.org/repos/dist/dev/incubator/eventmesh/${release_version}-${rc_version} https://dist.apache.org/repos/dist/release/incubator/eventmesh/ -m "transfer packages for ${release_version}-${rc_version}" #移动源码包与二进制包 +$ svn delete https://dist.apache.org/repos/dist/release/incubator/eventmesh/KEYS -m "delete KEYS" #清除原有release目录下的KEYS +$ svn cp https://dist.apache.org/repos/dist/dev/incubator/eventmesh/KEYS https://dist.apache.org/repos/dist/release/incubator/eventmesh/ -m "transfer KEYS for ${release_version}-${rc_version}" #拷贝dev目录KEYS到release目录 +``` + +### 3.确认dev和release下的包是否正确 + +- 确认[dev](https://dist.apache.org/repos/dist/dev/incubator/eventmesh/)下的`${release_version}-${rc_version}`已被删除 +- 删除[release](https://dist.apache.org/repos/dist/release/incubator/eventmesh/)目录下上一个版本的发布包,这些包会被自动保存在[这里](https://archive.apache.org/dist/incubator/eventmesh/) + +```shell +$ svn delete https://dist.apache.org/repos/dist/release/incubator/eventmesh/${last_release_version} -m "Delete ${last_release_version}" +``` + +### 4.在Apache Staging仓库发布版本 + +- 登录http://repository.apache.org , 使用Apache账号登录 +- 点击左侧的Staging repositories, +- 搜索EventMesh关键字,选择你最近上传的仓库,投票邮件中指定的仓库 +- 点击上方的`Release`按钮,这个过程会进行一系列检查 + +> 等仓库同步到其他数据源,一般需要24小时 + +### 5.GitHub版本发布 + +1.Tag the commit (on which the vote happened) with the release version without `-${RELEASE_CANDIDATE}`. 例如:after a successful vote on `v1.2-rc5`, the hash will be tagged again with `v1.2` only. + +2.在 [GitHub Releases](https://github.com/apache/incubator-eventmesh/releases) 页面的 `${release_version}` 版本上点击 `Edit` + +编辑版本号及版本说明,并点击 `Publish release` + +### 6.更新下载页面 + +等待并确认新的发布版本同步至 Apache 镜像后,更新如下页面: + +https://eventmesh.apache.org/download/ + +https://eventmesh.apache.org/zh/download/ + +GPG签名文件和哈希校验文件的下载连接应该使用这个前缀:`https://downloads.apache.org/incubator/eventmesh/` + +> 注意:项目下载链接应该使用 https://www.apache.org/dyn/closer.lua 而不是 closer.cgi 或者 mirrors.cgi + +### 7.邮件通知版本发布完成 + +> 请确保Apache Staging仓库已发布成功,一般是在该步骤的24小时后发布邮件 + +发邮件到 `dev@eventmesh.apache.org` 、 `announce@apache.org`和`general@incubator.apache.org` + +标题: + +``` +[ANNOUNCE] Apache EventMesh (incubating) ${release_version} available +``` + +正文: + +``` +Hi all, + +Apache EventMesh (incubating) Team is glad to announce the new release of Apache EventMesh (incubating) ${release_version}. + +Apache EventMesh (incubating) is a dynamic cloud-native eventing infrastructure used to decouple the application and backend middleware layer, which supports a wide range of use cases that encompass complex multi-cloud, widely distributed topologies using diverse technology stacks. + +Download Links: https://eventmesh.apache.org/projects/eventmesh/download/ + +Release Notes: https://eventmesh.apache.org/events/release-notes/v${release_version}/ + +Website: https://eventmesh.apache.org/ + +EventMesh Resources: +- Issue: https://github.com/apache/incubator-eventmesh/issues +- Mailing list: dev@eventmesh.apache.org + + + +Apache EventMesh (incubating) Team +``` + diff --git a/docs/zh/contribute/02-write-unit-test.md b/docs/zh/contribute/02-write-unit-test.md new file mode 100644 index 0000000000..055cdce31e --- /dev/null +++ b/docs/zh/contribute/02-write-unit-test.md @@ -0,0 +1,78 @@ +# 单元测试要求 + +- 每个单元测试都应该使用断言`assertions` 而不是 `System.out` 打印或者`if`语句 +- 每个单元测试都不应该调用其他用例,或者依赖于执行顺序 +- 每个单元测试都应该是可以循环执行的,并且单元测试不可以依赖外部环境,因为单元测试可能在持续集成环境中运行。 +- 每个单元测试的测试范围应该足够小且精准,以便于定位方法级别的问题。 + +## 路径和命名规则 + +- 单元测试应该写在`src/test/java`目录下。 +- 单元测试的配置文件应该放在`src/test/resources`目录下,如下示例: + - 将被测试的类:`src/main/java/org/apache/eventmesh/common/protocol/http/body/BaseResponseBody.java` + - 单元测试类:`src/test/java/org/apache/eventmesh/common/protocol/http/body/BaseResponseBodyTest.java` + - 单元测试配置文件:`src/test/resources/configuration.properties` +- 单元测试类的包名应该和被测试的类的包名相同 +- 单元测试的类的名字应该是`{被测试的类名+}Test`。 比如: + - 将被测试的类是:`EventMeshUtil` + - 单元测试类的类名就是: `EventMeshUtilTest` +- 每个单元测试的名字必须是 `test{+方法名}`,比如: + - 将被测试的方法:`addProp(String key, String val)` + - 单元测试的名字就是:`testAddProp` + +## 断言的用法 + + +### 常见的断言 + +| Methods | Instructions | +| :-------------- | :-------------- | +| `assertEquals` | 确定两个对象或原语类型是否相等 | +| `assertNotEquals` | 确定两个对象或原语类型是否不相等 | +| `assertTrue` | 确定给定的布尔值是否是 `true` | +| `assertFalse` | 确定给定的布尔值是否是 `false` | +| `assertNull` | 确定给定的对象是否是 `null` | +| `assertNotNull` | 确定给定的对象是否不是 `null` | +| `assertAll` | 如果同时处理多个逻辑,如果只有一个逻辑断言失败,整个测试将会失败| + +### 示例 + +#### `assertEquals()` + +```java +configuration.init(); +Assert.assertEquals("value1", configuration.eventMeshEnv); +``` + +#### `assertTrue()` + +```java +BaseResponseHeader header = BaseResponseHeader.buildHeader("200"); +Assert.assertTrue(header.toMap().containsKey(ProtocolKey.REQUEST_CODE)); +``` + +#### `assertFalse()` + +```java +Class nacosRegistryServiceClass = NacosRegistryService.class; +Field initStatus = nacosRegistryServiceClass.getDeclaredField("INIT_STATUS"); +initStatus.setAccessible(true); +Object initStatusField = initStatus.get(nacosRegistryService); +Assert.assertFalse((Boolean.parseBoolean(initStatusField.toString()))); +``` + +#### `assertNull()` + +```java +DefaultFullHttpResponse response = httpCommand.httpResponse(); +Assert.assertNull(response); +``` + +#### `assertNotNull()` + +```java +Codec.Decoder cd = new Codec.Decoder(); +ArrayList result = new ArrayList<>(); +cd.decode(null, buf, result); +Assert.assertNotNull(result.get(0)); +``` diff --git a/docs/zh/contribute/03-new-contributor-guidelines.md b/docs/zh/contribute/03-new-contributor-guidelines.md new file mode 100644 index 0000000000..5a8e42995f --- /dev/null +++ b/docs/zh/contribute/03-new-contributor-guidelines.md @@ -0,0 +1,262 @@ + +# 如何成为EventMesh的贡献者(Contributor) + +如果您想向 eventmesh 社区提交代码,成为的新贡献者(Contributor),请阅读本文档. + +本文档描述了如何向社区提交代码的一般流程。如果您在文档中发现任何问题,欢迎留下评论或建议。 + +## 准备工作 + +### 开发环境 + +- 您应该在您的开发环境中安装JDK,建议 JDK 8 及以上版本。 +- 您应该在您的开发环境中安装Gradle,建议 Gradle 7 及以上版本。 + +### 代码风格 + +将[EventMesh CheckStyle](https://github.com/apache/incubator-eventmesh/blob/master/style/checkStyle.xml) 文件导入到您的IDEA。 + +对于IDEA,您可以通过以下方式导入检查样式文件: +```shell + Editor -> Code Style -> Java -> Scheme -> Import Scheme -> CheckStyle Configuration +``` + +如果您在导入方案下看不到CheckStyle配置部分,您可以先安装CheckStyle-IDEA插件,就可以看到它。 + +您也可以使用`./gradlew check`来检查代码风格。 +(注意:这个命令将检查项目中的所有文件,当您提交一个项目时,CI将只检查这个项目中被修改的文件)。 + +CheckStyle-IDEA插件导入演示: + +a.如图安装CheckStyle-IDEA插件 + +![CheckStyle01](../../images/contribute/checkstyle01.png) + +b.下载完成后需要导入EventMesh的检查样式文件,如下步骤: + +1.如图: + +![CheckStyle02](../../images/contribute/checkstyle02.png) + +2.当点击+号之后会出现以下界面 + +![CheckStyle03](../../images/contribute/checkstyle03.png) + +标号1的地方简单取个名字即可,标号2的地方是EventMesh CheckStyle文件的位置,在项目的style文件夹下。 + +3.点击finish之后就会出现下图界面 + +![CheckStyle04](../../images/contribute/checkstyle04.png) + +将添加的样式检查文件勾选上并Apply + +c.当完成以上步骤之后就可以在您完成代码编写后进行样式检查了,步骤如下: + +1.选择添加的EM-checks文件。 + +![CheckStyle05](../../images/contribute/checkstyle05.png) + +2.点击这两个地方都可检查文件样式 + +![CheckStyle06](../../images/contribute/checkstyle06.png) + +这两个标号都只检测当前页的文件样式,标号2在当前页鼠标右键即可出现。 + +### 工作流程 + +以下是贡献者提交代码的工作流程: + +0. 在提交PR之前需要先创建一个ISSUE,它是用来表达你的想法的,比如你发现了代码中的bug,想修复这个bug,那么需要告知社区管理者或贡献者你的想法,就要创建一个ISSUE用于交流讨论。在EventMesh社区有ISSUE模板,可根据您提出的ISSUE中讨论的内容使用相应的模板。 + +ISSUE创建示例: + a.进入到项目仓库的主页,切换到issue标签,点击New issue + ![contributor01](../../images/contribute/zh/contribute14.png) + + b.就会出现下图界面 + ![contributor01](../../images/contribute/zh/contribute15.png) + 根据你的需要选择不同的ISSUE模板,如果你觉得没有模板合适,你可以选择打开一个空白模板。 + 当前EventMesh提供了六种ISSUE模板 + Bug report: 发现代码bug,请使用此模板 + Documentation Related: 文档相关的,请使用此模板 + Enhancement Request: 代码优化,增强代码实现的,请使用此模板 + Feature Request: 为EventMesh提供新的特性功能的使用此模板 + Question: 对于EventMesh有疑问的,或者有什么不明白的想要提问的,请使用此模板 + Unit Test: 想为EventMesh做一些单元测试的,请使用此模板 + + c.根据模板的提示,完成issue内容填写。主要是描述清楚问题所在和解决方案就可以了 + + [ISSUE实例](https://github.com/apache/incubator-eventmesh/issues/2148) + 如图: + ![contributor01](../../images/contribute/zh/contribute16.png) + +ISSUE与PR关联: + 后续提交PR的时候,PR的标题和内容应该跟ISSUE完成关联,这样才符合开源的规范,如下图所示 + + ![contributor01](../../images/contribute/zh/contribute17.png) + + 上图ISSUE编号为2148,那么你的PR标题前就是 [ISSUE #2148],这样就关联上了。 + + +1. 在issue创建完成后,将源仓库的项目eventmesh fork到自己仓库当中 +例: + a.点击eventmesh右上角的fork + ![contributor01](../../images/contribute/zh/contribute01.png) + b.就会出现下图,点击Create fork即可将eventmesh fork到自己的仓库 + ![contributor02](../../images/contribute/zh/contribute02.png) + + +2. fork完成后,克隆自己仓库的代码到本地 +```git +git clone git@github.com:yourgithub/incubator-eventmesh.git +``` + +3. 创建一个新的分支进行工作 +```git +git checkout -b fix_patch_xx +``` + +4. 让您的分支保持同步 +```git +git remote add upstream git@github.com:apache/incubator-eventmesh.git +git fetch upstream master:upstream_master +git rebase upstream_master +``` + +5. 提交您的修改(确保您的提交信息简洁明了) + +**特别注意:在提交代码之前要确保你提交代码的邮箱要与GitHub邮箱一致,不然在统计contributor数量时会发生无法正常计入的情况** + +- 在IDEA中打开Terminal(终端),输入以下命令查看本地使用的邮箱信息 +```git +git config --global --list +``` +如图: +![contributor12](../../images/contribute/zh/contribute12.png) +如果你在提交之前还未登陆邮箱,使用注册GitHub账号时的邮箱 + +- 如果你发现你的邮箱与GitHub邮箱不一致可通过以下git命令进行修改 +```git +git config --global user.name 你的目标用户名 +git config --global user.email 你的目标邮箱名 +``` +如图: +![contributor13](../../images/contribute/zh/contribute13.png) +修改邮箱同理(也可以用这个命令来登陆邮箱) + +例:用IDEA提交代码为例,如果您在IDEA本地修改完毕 + a.点击Commit,点击图片中两个地方中任意一个即可 + ![contributor03](../../images/contribute/zh/contribute03.png) + b.就会出现以下图中界面 + ![contributor04](../../images/contribute/zh/contribute04.png) + (注:如果是新添加的文件需要Add一下,再Commit,一般IDEA都会提示,如果没有提示,按下图操作即可,文件由红色变为绿色Add成功) + ![contributor09](../../images/contribute/zh/contribute09.png) + +6. 将您的提交推送到自己的fork仓库 + a.需要push到远程仓库中,注意是您自己的仓库,您需要点击 + ![contributor05](../../images/contribute/zh/contribute05.png) + 或者是 + ![contributor06](../../images/contribute/zh/contribute06.png) + b.就会出现以下界面,确认无误后点击右下角push,就push到自己的仓库了 + ![contributor07](../../images/contribute/zh/contribute07.png) + c.当您成功push到自己仓库就会出现下图的提示(在IDEA界面的右下角) + ![contributor08](../../images/contribute/zh/contribute08.png) + +7. 创建一个Pull Request (PR) +例: + a.当您成功push到自己的仓库当中后,进入自己的仓库主页,会出现下图界面 + ![contributor10](../../images/contribute/zh/contribute10.png) + b.点击Compare & pull request,就会出现以下界面,按照图中操作即可创建pull request + ![contributor11](../../images/contribute/zh/contribute11.png) + + +## 解释 + +原始仓库:https://github.com/apache/incubator-eventmesh Eventmesh的apache仓库在文中被称为原始仓库。 + +fork库: 从 https://github.com/apache/eventmesh fork到你自己的个人仓库,成为一个fork库。 + +因此,首先需要将原EventMesh仓库fork到你自己的仓库中。 + +## 开发分支 + +**EventMesh 当前的开发分支是 master。请向该分支提交 PR。** + +- 我们建议您在本地master分支的基础上创建一个新的开发分支,在该开发分支上提交代码,并基于该分支向原始仓库的master分支提交PR。 + +## 贡献类别 + +### 错误反馈或错误修复 + +- 无论是bug反馈还是修复,都需要先创建一个ISSUE,对bug进行详细描述,这样社区就可以通过问题记录轻松找到并查看问题和代码。bug反馈问题通常需要包含完整的bug信息描述和可重现的场景。 + +### 功能的实现,重构 + +- 如果你计划实现一个新功能(或重构),一定要通过 ISSUE 或其他方式与 eventmesh 核心开发团队沟通,并在沟通过程中详细描述新功能(或重构)、机制和场景。 + +### 文档改进 + +- 您可以在 [eventmesh-docs](https://github.com/apache/incubator-eventmesh/tree/master/docs) 找到 eventmesh 文档。文档的补充或改进对 eventmesh 是必不可少的。 + +## 贡献方式 + +新的贡献者有两种方式来为 eventmesh 社区作出贡献: + +- 如果您在 eventmesh 代码中发现了一个你想修复的 bug,或者你为 eventmesh 提供了一个新功能,请在 eventmesh 中提交一个Issue,并向 eventmesh 提交一份 PR。 + +- eventmesh 社区有其他贡献者提出的ISSUE,这里是社区整理的 [`issue for first-time contributors`](https://github.com/apache/incubator-eventmesh/issues/888) 是相对简单的 PR,可以帮助你熟悉向 eventmesh 社区做贡献的过程。 + +## 提交ISSUE指南 + +- 如果您不知道如何在 eventmesh 上提Issue,请阅读前文,或阅读 [about the issue](https://docs.github.com/cn/issues/tracking-your-work-with-issues/quickstart) 。 + +- 在 eventmesh 社区,有Issue模板可以参考,如果类型匹配请使用该模板,如果Issue模板不符合你的要求,你可以开一个空的Issue模板,对于问题请带上其匹配的功能标签。 + +- 对于Issue的名称,请用一句话简要描述你的Issue或目的,为了更好的全球交流,请用英文书写。 + +## Pull Request(PR)提交指南 + +- 如果你不知道如何为 eventmesh 发起一个 PR,请阅读前文,或参见 [about pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) 。 + +- 无论是 bug 修复,还是新功能开发(如果这个 pr 是新功能开发,那么关于新功能的文档更新应该包括在这个 pr 中),请向当前开发分支 master 提交 PR。 + +- 提交的pr应该遵循eventmesh提供的模板以及需要写的提交信息,简单描述你提交的pr是做什么的就可以了,请阅读 [模板详情](https://github.com/apache/incubator-eventmesh/blob/master/.github/PULL_REQUEST_TEMPLATE.md) 。 + +- 你提交的PR需要与你要修复的问题,或你要提出的问题相关联,所以你的PR标题应该以[ISSUE #xx]开头。 + +- 如果你的修改是关于一个错别字或小的优化,你不需要创建一个问题,只要提交一个PR和标题为[MINOR]。 + +**注意:** + +- 一个拉动请求不应该太大。如果需要大量的修改,最好将这些修改分成几个单独的 PR。 + +- 在创建PR后,一个或多个提交人将帮助审查该拉动请求,在批准后,该PR将被合并到eventmesh主源库中,相关的Issue将被关闭。 + +## 审查 + +### PR审查 + +所有的代码都应该由一个或多个提交者进行良好的审查。一些原则。 + +- 可读性。重要的代码应该有良好的文档。遵守我们的 [代码风格](https://github.com/apache/incubator-eventmesh/blob/master/style/checkStyle.xml) 。 + +- 优雅性。新的函数、类或组件应该是精心设计的。 + +- 可测试性。重要的代码应该经过良好的测试(高单元测试覆盖率)。 + +### 许可证审查 + +EventMesh遵循 [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) 政策。所有源文件应 +在文件头中添加Apache许可证头。EventMesh 使用 [apache/skywalking-eyes](https://github.com/apache/skywalking-eyes) 来检查 +源文件的头。 + +### PR合并 + +当一个PR被至少一个提交者批准后,它就可以被合并了。合并前,提交者可以对提交信息进行修改,要求提交的 +消息要清楚,不能有重复,并使用 Squash 和 Merge 来确保一个 PR 只应包含一个提交。 +对于大型的多人PR,使用Merge合并,在合并前通过rebase修复提交。 + +## 社区 + +### 联系我们 + +Mail: dev@eventmesh.apache.org diff --git a/docs/zh/contribute/_category_.json b/docs/zh/contribute/_category_.json new file mode 100644 index 0000000000..56d36f918e --- /dev/null +++ b/docs/zh/contribute/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 5, + "label": "Contribute", + "collapsed": false +} diff --git a/docs/zh/desing-document/01-workflow.md b/docs/zh/desing-document/01-workflow.md new file mode 100644 index 0000000000..444c09454d --- /dev/null +++ b/docs/zh/desing-document/01-workflow.md @@ -0,0 +1,258 @@ +# EventMesh工作流 + +## 业务场景 + +图中你正在构建一个简单的电商订单管理系统,系统能够接收和调配新的订单,调配流程需要处理所有的订单创建,付款处理以及发货处理。 + +为了实现高可用和高性能,你可以使用事件驱动架构(EDA)构建微服务应用去处理商店前端,订单管理,支付处理和发货管理。你可以在云上部署整个系统。要处理高并发,你可以利用消息系统缓冲,并扩展多个微服务实例。架构类似于: + +![Workflow Use Case](../../images/design-document/workflow-use-case.jpg) + +当每个微服务都在自己的事件通道上运行时,EventMesh在执行事件编排方面发挥着至关重要的作用。 + +我们使用 [CNCF Serverless工作流](https://serverlessworkflow.io/) 来描述此事件工作流编排。 + +## CNCF Serverless工作流 + +CNCF Serverless工作流定义了一个厂商中立、开源和完全社区驱动的生态系统,用于定义和运行针对Serverless技术领域的基于DSL的工作流。 + +Serverless工作流定义了一种领域特定语言(DSL)来描述有状态和无状态的基于工作流的serverless函数和微服务编排。 + +详见[官方github](https://github.com/serverlessworkflow/specification) + +## EventMesh工作流 + +我们利用Serverless工作流DSL来描述EventMesh工作流。根据其规范,工作流由一系列用于描述控制流逻辑的工作流状态组成。目前,我们仅支持与事件相关的工作流状态。请参见[工作流DSL设计](#workflow-dsl-design-wip)中支持的状态。 + +`工作流状态`可以包含通用的`操作`,或在工作流执行期间应调用的服务/函数。这些`操作`可以引用可复用的`函数`定义(应如何调用这些函数/服务),还可以引用触发基于事件的服务调用的事件,以及要等待的事件,这些事件表示这种基于事件的服务调用完成。 + +在EDA解决方案中,我们通常使用AsyncAPI定义事件驱动的微服务。Serverless工作流“函数”定义支持使用AsyncAPI定义调用语义。有关详细信息,请参见[Using Funtions for AsyncAPI Service](https://github.com/serverlessworkflow/specification/blob/main/specification.md#using-functions-for-async-api-service-invocations)。 + +### AsyncAPI + +AsyncAPI是一项开源计划,旨在改善事件驱动体系结构(EDA)的当前状态。我们的长期目标是让使用EDA和使用REST API一样容易。包括从文档到代码生成、发现到事件管理。现在应用于REST API的大多数流程也适用于事件驱动/异步API。 + +详见[AsyncAPI官网](https://www.asyncapi.com/docs/getting-started) + +### 工作流示例 + +在本示例中,我们构建了上面订单管理系统的事件驱动工作流。 + +首先,我们需要为我们的微服务应用定义AsyncAPI。 + +- 在线商店应用程序 + +```yaml +asyncapi: 2.2.0 +info: + title: Online Store application + version: '0.1.0' +channels: + store/order: + subscribe: + operationId: newStoreOrder + message: + $ref : '#/components/NewOrder' + +``` + +- 订单服务 + +```yaml +asyncapi: 2.2.0 +info: + title: Order Service + version: '0.1.0' +channels: + order/inbound: + publish: + operationId: sendOrder + message: + $ref : '#/components/Order' + order/outbound: + subscribe: + operationId: processedOrder + message: + $ref : '#/components/Order' +``` + +- 支付服务 + +```yaml +asyncapi: 2.2.0 +info: + title: Payment Service + version: '0.1.0' +channels: + payment/inbound: + publish: + operationId: sendPayment + message: + $ref : '#/components/OrderPayment' + payment/outbound: + subscribe: + operationId: paymentReceipt + message: + $ref : '#/components/OrderPayment' +``` + +- 物流服务 + +```yaml +asyncapi: 2.2.0 +info: + title: Shipment Service + version: '0.1.0' +channels: + shipment/inbound: + publish: + operationId: sendShipment + message: + $ref : '#/components/OrderShipment' +``` + +接下来,定义描述订单管理业务逻辑的订单工作流。 + +```yaml +id: storeorderworkflow +version: '1.0' +specVersion: '0.8' +name: Store Order Management Workflow +states: + - name: Receive New Order Event + type: event + onEvents: + - eventRefs: + - NewOrderEvent + actions: + - eventRef: + triggerEventRef: OrderServiceSendEvent + resultEventRef: OrderServiceResultEvent + - eventRef: + triggerEventRef: PaymentServiceSendEvent + resultEventRef: PaymentServiceResultEvent + transition: Check Payment Status + - name: Check Payment Status + type: switch + dataConditions: + - name: Payment Successfull + condition: "${ .payment.status == 'success' }" + transition: Send Order Shipment + - name: Payment Denied + condition: "${ .payment.status == 'denied' }" + end: true + defaultCondition: + end: true + - name: Send Order Shipment + type: operation + actions: + - eventRef: + triggerEventRef: ShipmentServiceSendEvent + end: true +events: + - name: NewOrderEvent + source: file://onlineStoreApp.yaml#newStoreOrder + type: asyncapi + kind: consumed + - name: OrderServiceSendEvent + source: file://orderService.yaml#sendOrder + type: asyncapi + kind: produced + - name: OrderServiceResultEvent + source: file://orderService.yaml#processedOrder + type: asyncapi + kind: consumed + - name: PaymentServiceSendEvent + source: file://paymentService.yaml#sendPayment + type: asyncapi + kind: produced + - name: PaymentServiceResultEvent + source: file://paymentService.yaml#paymentReceipt + type: asyncapi + kind: consumed + - name: ShipmentServiceSendEvent + source: file://shipmentService.yaml#sendShipment + type: asyncapi + kind: produced +``` + +对应的工作流图如下: + +![Workflow Diagram](../../images/design-document/workflow-diagram.png) + +## EventMesh工作流引擎 + +在下面的体系结构图中, EventMesh目录, EventMesh工作流引擎 和 EventMesh Runtime在三个不同的处理器中运行。 + +![Workflow Architecture](../../images/design-document/workflow-architecture.jpg) + +运行工作流的步骤如下: + +1. 在环境中部署发布者和订阅者应用程序。 + 使用AsyncAPI描述应用程序API,生成asyncAPI yaml。 + 使用AsyncAPI在EventMesh目录中注册发布者和订阅者应用程序。 + +2. 在EventMesh工作流引擎中注册Serverless工作流DSL。 + +3. 工作流引擎从EventMesh目录查询发布服务器和订阅服务器的需要的工作流DSL`函数`。 + +4. 事件驱动App将事件发布到EventMesh Runtime触发工作流。EventMesh工作流引擎发布和订阅事件、编排事件。 + +### EventMesh Catalog 设计 + +EventMesh目录存储发布者、订阅者和通道元数据。由以下模块组成: + +- AsyncAPI解析器 + + 使用AsyncAPI社区提供的SDK ([tool list](https://www.asyncapi.com/docs/community/tooling)), + 解析并验证AsyncAPI yaml输入,并生成AsyncAPI定义。 + +- 发布者, 通道, 订阅者模块 + + 从AsyncAPI定义存储发布者、订阅者和通道信息。 + +### EventMesh工作流引擎设计 + +工作流引擎由以下模块组成: + +- 工作流解析器 + + 使用Serverless Workflow社区提供的SDK([SDKs](https://github.com/serverlessworkflow/specification#sdks)), + 解析和验证工作流DSL输入,并生成工作流定义。 + +- 工作流模块 + + 管理工作流实例的生命周期,从创建、启动、停止到销毁。 + +- 状态模块 + + 管理工作流状态生命周期。支持与事件相关的状态,and the supported state list below is Work-in-Progress. + + | 工作流状态 | 描述 | + | --- | --- | + | Operation | 执行Actions中定义的AsyncAPI函数 | + | Event | 检查定义的事件是否匹配,如果匹配,执行定义的AsyncAPI函数 | + | Switch | 检查事件是否与事件条件匹配,并执行定义的AsyncAPI函数 | + | Parallel | 并行执行定义的AsyncAPI函数 | + | ForEach | 迭代输入集合并执行定义的AsyncAPI函数 | + +- 行为模块 + + 管理函数中的行为。 + +- 函数模块 + + 通过在EventMesh Runtime中创建发布者和/或订阅者来管理AsyncAPI函数,并管理发布者/订阅者生命周期。 + + | AsyncAPI 操作 | EventMesh Runtime | + | --- | --- | + | Publish | Publisher | + | Subscribe | Subscriber | + +- 事件模块 + + 使用工作流DSL中定义的规则管理CloudEvent数据模型,包括事件过滤器、关联和转换。 + +- 重试模块 + + 管理事件发布到EventMesh Runtime的重试逻辑。 diff --git a/docs/zh/desing-document/02-runtime-protocol.md b/docs/zh/desing-document/02-runtime-protocol.md new file mode 100644 index 0000000000..d5f155602f --- /dev/null +++ b/docs/zh/desing-document/02-runtime-protocol.md @@ -0,0 +1,420 @@ +# TCP协议文档 + +#### 1. 协议格式 + +![dataFlow](../../images/design-document/tcp-protocol.png) + +**消息组成详解:** + +``` +魔术字:9位,当前值为“EventMesh” + +通信协议版本号:4位,当前值为“0000” + +消息总长度值(length):4位,int类型 + +消息头长度值(headerLength):4位,int类型 + +消息头(header):长度 = headerLength + +消息体(body):长度 = length - headerLength - 4 - 4 +``` + +#### 2. 业务逻辑层 + ++ 消息组成 + +消息头(header)+ 消息体(body) + +```java +public class Package { + + private Header header; + private Object body; +} + + +public class Header { + + private Command cmd; + private int code; + private String msg; + private String seq; +} +``` + ++ 详解 + +消息头(header):类型为Header,Header中有Command字段,用于区分不同的消息类型 + +消息体(body):对于不同的消息类型,body的类型不同 + +| 消息命令字 | body类型 | +| ------------------------------------------------------------ | ------------ | +| HEARTBEAT_REQUEST, HEARTBEAT_RESPONSE, HELLO_RESPONSE, CLIENT_GOODBYE_REQUEST, CLIENT_GOODBYE_RESPONSE, SERVER_GOODBYE_REQUEST, SERVER_GOODBYE_RESPONSE, LISTEN_REQUEST, LISTEN_RESPONSE, UNSUBSCRIBE_REQUEST, SUBSCRIBE_RESPONSE, UNSUBSCRIBE_RESPONSE, ASYNC_MESSAGE_TO_SERVER_ACK, BROADCAST_MESSAGE_TO_SERVER_ACK | 无 | +| HELLO_REQUEST | UserAgent | +| SUBSCRIBE_REQUEST | Subscription | +| REQUEST_TO_SERVER, REQUEST_TO_CLIENT, RESPONSE_TO_SERVER, RESPONSE_TO_CLIENT, ASYNC_MESSAGE_TO_SERVER, ASYNC_MESSAGE_TO_CLIENT, BROADCAST_MESSAGE_TO_SERVER, BROADCAST_MESSAGE_TO_CLIENT, ASYNC_MESSAGE_TO_CLIENT_ACK, BROADCAST_MESSAGE_TO_CLIENT_ACK, RESPONSE_TO_CLIENT_ACK, REQUEST_TO_CLIENT_ACK | OpenMessage | +| REDIRECT_TO_CLIENT | RedirectInfo | + +#### 3. Client 与 Eventmesh-Runtime(Server)交互场景详解 + +```java +public enum Command { + + //心跳 + HEARTBEAT_REQUEST(0), //client发给server的心跳包 + HEARTBEAT_RESPONSE(1), //server回复client的心跳包 + + //握手 + HELLO_REQUEST(2), //client发给server的握手请求 + HELLO_RESPONSE(3), //server回复client的握手请求 + + //断连 + CLIENT_GOODBYE_REQUEST(4), //client主动断连时通知server + CLIENT_GOODBYE_RESPONSE(5), //server回复client的主动断连通知 + SERVER_GOODBYE_REQUEST(6), //server主动断连时通知client + SERVER_GOODBYE_RESPONSE(7), //client回复server的主动断连通知 + + //订阅管理 + SUBSCRIBE_REQUEST(8), //client发给server的订阅请求 + SUBSCRIBE_RESPONSE(9), //server回复client的订阅请求 + UNSUBSCRIBE_REQUEST(10), //client发给server的取消订阅请求 + UNSUBSCRIBE_RESPONSE(11), //server回复client的取消订阅请求 + + //监听 + LISTEN_REQUEST(12), //client发给server的启动监听请求 + LISTEN_RESPONSE(13), //server回复client的监听请求 + + //RR + REQUEST_TO_SERVER(14), //client将RR请求发送给server + REQUEST_TO_CLIENT(15), //server将RR请求推送给client + REQUEST_TO_CLIENT_ACK(16), //client收到RR请求后ACK给server + RESPONSE_TO_SERVER(17), //client将RR回包发送给server + RESPONSE_TO_CLIENT(18), //server将RR回包推送给client + RESPONSE_TO_CLIENT_ACK(19), //client收到回包后ACK给server + + //异步事件 + ASYNC_MESSAGE_TO_SERVER(20), //client将异步事件发送给server + ASYNC_MESSAGE_TO_SERVER_ACK(21), //server收到异步事件后ACK给client + ASYNC_MESSAGE_TO_CLIENT(22), //server将异步事件推送给client + ASYNC_MESSAGE_TO_CLIENT_ACK(23), //client收到异步事件后ACK给server + + //广播 + BROADCAST_MESSAGE_TO_SERVER(24), //client将广播消息发送给server + BROADCAST_MESSAGE_TO_SERVER_ACK(25), //server收到广播消息后ACK给client + BROADCAST_MESSAGE_TO_CLIENT(26), //server将广播消息推送给client + BROADCAST_MESSAGE_TO_CLIENT_ACK(27), //client收到广播消息后ACK给server + + //重定向指令 + REDIRECT_TO_CLIENT(30), //server将重定向指令推动给client +} +``` + +#### 4. Client发起交互 + +| 场景 | Client向Server发送消息命令字 | Server回复Client消息的命令字 | 说明 | +| -------------- | ---------------------------- | ------------------------------- | ---- | +| 握手 | HELLO_REQUEST | HELLO_RESPONSE | | +| 心跳 | HEARTBEAT_REQUEST | HEARTBEAT_RESPONSE | | +| 订阅 | SUBSCRIBE_REQUEST | SUBSCRIBE_RESPONSE | | +| 取消订阅 | UNSUBSCRIBE_REQUEST | UNSUBSCRIBE_RESPONSE | | +| 开始监听消息 | LISTEN_REQUEST | LISTEN_RESPONSE | | +| 发送RR请求 | REQUEST_TO_SERVER | RESPONSE_TO_CLIENT | | +| 发送RR回包 | RESPONSE_TO_SERVER | 无 | | +| 发送异步事件 | ASYNC_MESSAGE_TO_SERVER | ASYNC_MESSAGE_TO_SERVER_ACK | | +| 发送广播事件 | BROADCAST_MESSAGE_TO_SERVER | BROADCAST_MESSAGE_TO_SERVER_ACK | | +| 客户端主动断连 | CLIENT_GOODBYE_REQUEST | CLIENT_GOODBYE_RESPONSE | | + +#### 5. Server发起交互 + +| 场景 | Server向Client发送消息命令字 | Client回复Server消息命令字 | 说明 | +| ------------------ | ---------------------------- | ------------------------------- | ---- | +| 客户端接收RR请求 | REQUEST_TO_CLIENT | REQUEST_TO_CLIENT_ACK | | +| 客户端接收RR回包 | RESPONSE_TO_CLIENT | RESPONSE_TO_CLIENT_ACK | | +| 客户端接收异步事件 | ASYNC_MESSAGE_TO_CLIENT | ASYNC_MESSAGE_TO_CLIENT_ACK | | +| 客户端接收广播事件 | BROADCAST_MESSAGE_TO_CLIENT | BROADCAST_MESSAGE_TO_CLIENT_ACK | | +| 服务端主动断连 | SERVER_GOODBYE_REQUEST | 无 | | +| 服务端进行重定向 | REDIRECT_TO_CLIENT | 无 | | +| | | | | + +#### 6. 消息类型 + ++ 发送RR消息 + +![rr-msg](../../images/design-document/sync-message.png) + ++ 发送异步单播消息 + +![async-msg](../../images/design-document/async-message.png) + ++ 发送广播消息 + +![broadcast-msg](../../images/design-document/broadcast-message.png) + +## HTTP协议文档 + +Java类`LiteMessage`的`content`字段表示一个特殊的协议,因此,如果您要使用eventmesh-sdk-java的http-client,则只需设计协议的`content`即可。`LiteMessage`组成如下: + +```java +public class LiteMessage { + + private String bizSeqNo; + + private String uniqueId; + + private String topic; + + private String content; + + private Map prop; + + private long createTime = System.currentTimeMillis(); +} +``` + +#### 1. 消息发送方式与组成 + +**消息发送方式**:POST方式 + +**消息组成**:请求头(RequestHeader) + 请求体(RequestBody) + ++ 心跳消息 + +**RequestHeader** + +| Key | 说明 | +| -------- | ---------------- | +| Env | client所属环境 | +| Region | client所属区域 | +| Idc | client所属IDC | +| Dcn | client所在DCN | +| Sys | client所属子系统 | +| Pid | client进程号 | +| Ip | client Ip | +| Username | client 用户名 | +| Passwd | client 密码 | +| Version | 协议版本 | +| Language | 语言描述 | +| Code | 请求码 | + +**RequestBody** + +| Key | 说明 | +| ----------------- | ------------------------------ | +| clientType | 客户端类型 | +| heartbeatEntities | 心跳实体,包含topic、url等信息 | + ++ 订阅消息: + +**RequestHeader** + +与心跳消息一致 + +**RequestBody** + +| Key | 说明 | +| ----- | ----------------- | +| topic | 客户端订阅的topic | +| url | topic对应的url | + ++ 取消订阅消息: + +**RequestHeader** + +与心跳消息一致 + +**RequestBody** + +与订阅消息一致 + ++ 发送异步事件: + +**RequestHeader** + +与心跳消息一致 + +**RequestBody** + +| Key | 说明 | +| -------- | ----------------------- | +| topic | 客户端请求的topic | +| content | 客户端发送的topic的内容 | +| ttl | 客户端请求超时时间 | +| bizSeqNo | 客户端请求业务流水号 | +| uniqueId | 客户端请求消息唯一标识 | + +#### 2. Client发起交互 + +| 场景 | Client向Server发送消息请求码 | Server回复Client消息的响应码 | 说明 | +| ------------ | ---------------------------- | --------------------------------------- | ---- | +| 心跳 | HEARTBEAT(203) | SUCCESS(0)/EVENTMESH_HEARTBEAT_ERROR(19) | | +| 订阅 | SUBSCRIBE(206) | SUCCESS(0)/EVENTMESH_SUBSCRIBE_ERROR(17) | | +| 取消订阅 | UNSUBSCRIBE(207) | SUCCESS(0)/EVENTMESH_UNSUBSCRIBE_ERROR(18) | | +| 发送异步事件 | MSG_SEND_ASYNC(104) | SUCCESS(0)/EVENTMESH_SEND_ASYNC_MSG_ERR(14) | | + +#### 3. Server发起交互 + +| 场景 | Server向Client发送消息请求码 | Client回复Server消息响应码 | 说明 | +| ------------------ | ---------------------------- | -------------------------- | ---------------------- | +| 客户端接收异步事件 | HTTP_PUSH_CLIENT_ASYNC(105) | retCode | retCode值为0时代表成功 | + +## gRPC 协议文档 + +#### 1. protobuf + +在 `eventmesh-protocol-gprc` 模块有 Eventmesh gRPC 客户端的 protobuf 文件. the protobuf 文件路径是 `/src/main/proto/eventmesh-client.proto`. + +用gradle build 生成 gRPC 代码在 `/build/generated/source/proto/main`. 生成代码用于 `eventmesh-sdk-java` 模块. + +#### 2. gRPC 数据模型 + ++ 消息 + +以下消息数据模型用于 `publish()`, `requestReply()` 和 `broadcast()` APIs. + +``` +message RequestHeader { + string env = 1; + string region = 2; + string idc = 3; + string ip = 4; + string pid = 5; + string sys = 6; + string username = 7; + string password = 8; + string language = 9; + string protocolType = 10; + string protocolVersion = 11; + string protocolDesc = 12; +} + +message SimpleMessage { + RequestHeader header = 1; + string producerGroup = 2; + string topic = 3; + string content = 4; + string ttl = 5; + string uniqueId = 6; + string seqNum = 7; + string tag = 8; + map properties = 9; +} + +message BatchMessage { + RequestHeader header = 1; + string producerGroup = 2; + string topic = 3; + + message MessageItem { + string content = 1; + string ttl = 2; + string uniqueId = 3; + string seqNum = 4; + string tag = 5; + map properties = 6; + } + + repeated MessageItem messageItem = 4; +} + +message Response { + string respCode = 1; + string respMsg = 2; + string respTime = 3; +} +``` + ++ 订阅 + +以下订阅数据模型用于 `subscribe()` 和 `unsubscribe()` APIs. + +``` +message Subscription { + RequestHeader header = 1; + string consumerGroup = 2; + + message SubscriptionItem { + enum SubscriptionMode { + CLUSTERING = 0; + BROADCASTING = 1; + } + + enum SubscriptionType { + ASYNC = 0; + SYNC = 1; + } + + string topic = 1; + SubscriptionMode mode = 2; + SubscriptionType type = 3; + } + + repeated SubscriptionItem subscriptionItems = 3; + string url = 4; +} +``` + ++ 心跳 + +以下心跳数据模型用于 `heartbeat()` API. + +``` +message Heartbeat { + enum ClientType { + PUB = 0; + SUB = 1; + } + + RequestHeader header = 1; + ClientType clientType = 2; + string producerGroup = 3; + string consumerGroup = 4; + + message HeartbeatItem { + string topic = 1; + string url = 2; + } + + repeated HeartbeatItem heartbeatItems = 5; +} +``` + +#### 3. gRPC 服务接口 + ++ 事件生产端服务 APIs + +``` +service PublisherService { + # 异步事件生产 + rpc publish(SimpleMessage) returns (Response); + + # 同步事件生产 + rpc requestReply(SimpleMessage) returns (Response); + + # 批量事件生产 + rpc batchPublish(BatchMessage) returns (Response); +} +``` + ++ 事件消费端服务 APIs + +``` +service ConsumerService { + # 所消费事件通过 HTTP Webhook推送事件 + rpc subscribe(Subscription) returns (Response); + + # 所消费事件通过 TCP stream推送事件 + rpc subscribeStream(Subscription) returns (stream SimpleMessage); + + rpc unsubscribe(Subscription) returns (Response); +} +``` + ++ 客户端心跳服务 API + +``` +service HeartbeatService { + rpc heartbeat(Heartbeat) returns (Response); +} +``` diff --git a/docs/zh/desing-document/03-stream.md b/docs/zh/desing-document/03-stream.md new file mode 100644 index 0000000000..9f733d82b7 --- /dev/null +++ b/docs/zh/desing-document/03-stream.md @@ -0,0 +1,115 @@ +# EventMesh Stream + +## 事件流概述 + +事件流是发布/订阅架构模式的一种实现,它包括以下几个部分 + +- 消息或事件:状态变化。 + +- 主题:消息中间件代理中的分区。 + +- 消费者:可以从代理主题订阅读取事件。 + +- 生产者:生成事件 + +事件流是事件的连续流动,为了维持事件之间的秩序,事件流应该以特定的方式从生产者流向消费者。 + +## 要求 + +### 功能要求 + +| 需求编号 | 需求描述 | 注释 | +| -------------- | ----------------------- | -------- | +| F-1 | EventMesh用户应该能够在 EventMesh 中实现事件流功能 | 功能性 | +| F-2 | EventMesh用户可以为路由、过滤、转换等应用动态用户特定逻辑 | 功能性 | + +## 设计细节 + +我们引入了 EventMesh Stream 组件,允许我们在 Apache Camel 中本地使用来自 Spring Cloud Stream 的编程模型和绑定器抽象。 + +[Spring-Cloud-Stream](https://spring.io/projects/spring-cloud-stream) Spring Cloud Stream是一个用于构建 +与共享消息传递系统连接的、高度可扩展的事件驱动微服务框架。 + +[Apache Camel](https://camel.apache.org/) Camel 是一个开源集成框架,使您能够快速轻松地集成各种消费或生产数据的系统。 + +## 架构 + +![Stream Architecture](../../images/design-document/stream-architecture.png) + +## 设计 + +### EventMesh-Stream 组件 + +- Event(事件) +- Event Channel(事件通道) +- Event EndPoint(事件端点) +- Event Pipes & Filters(事件管道和过滤器) +- Event Routes(事件路由器) +- Event Converter(事件转换器) + +#### Event(事件) + +> 事件是系统中传输数据的最小单位。它的结构分为标题、正文和附件。 + +#### Event Channel(事件通道) + +> 事件通道是系统中的逻辑通道,我们是通过 Spring Cloud Stream 编程模型实现的,它具有围绕消息通道的抽象功能(截至目前用的是 Spring `MessageChannel`)。 + +#### Event EndPoint(事件端点) + +> 事件端点是应用程序和消息传递系统之间的接口。我们可以定义两种类型的端点 + +- 消费者端点 - 出现在路由开始并从传入通道读取传入事件。 +- 生产者端点 - 出现在路由的末尾并将传入事件写入传出通道。 + +#### Event Pipes & Filters(事件管道和过滤器) + +> 我们可以通过创建过滤器链(Apache Camel `Processor`)来构建路由,其中一个过滤器的输出被用于管道中下一个过滤器的输入。管道的主要优点是可以创建复杂的事件处理逻辑。 + +#### Event Routes(事件路由器) + +> 事件路由器是消费者的一种过滤器,并根据决策标准将它们重定向到适当的目标端点。 + +#### Event Converter(事件转换器) + +> 事件转换器用于修改事件内容,将其转换为不同的格式(换而言之 cloudevents -> Event (Camel) -> Binder Message(Spring Message),反之亦然)。 + +## EventMesh-Stream 组件接口 + +### Component(组件) + +Component 接口是主要的入口点,您可以使用 Component 对象作为工厂来创建 EndPoint 对象。 + +![Stream Component Interface](../../images/design-document/stream-component-interface.png) + +### EndPoint(端点) + +EndPoint 作为创建消费者、生产者和事件对象的工厂。 + +- `createConsumer()` — 创建消费者端点,该端点表示路由开始的源端点。 +- `createProducer()` — 创建生产者端点,该端点表示路由末端的目标端点。 + +![Stream Component Routes](../../images/design-document/stream-component-routes.png) + +#### Producer(生产者) + +用户可以创建以下类型的生产者 +> 同步生产者:处理线程阻塞,直到生产者完成事件处理。 + +![Stream Sync Producer](../../images/design-document/stream-sync-producer.png) + +未来将会实现的生产者类型: + +- 异步生产者 - 生产者在子线程中处理事件。 + +#### Consumer(消费者) + +用户可以创建以下类型的消费者 +> 事件驱动的消费者:当消息绑定器调用消费者中的方法时,开始处理传入请求。 + +![Stream Event-Driven Consumer](../../images/design-document/stream-event-driven-consumer.png) + +未来将会实现的消费者类型: + +- 定时轮训消费者 +- 自定义轮询消费者 diff --git a/docs/zh/desing-document/05-metrics-export.md b/docs/zh/desing-document/05-metrics-export.md new file mode 100644 index 0000000000..38be6e07f8 --- /dev/null +++ b/docs/zh/desing-document/05-metrics-export.md @@ -0,0 +1,47 @@ +# EventMesh 指标(OpenTelemetry 和 Prometheus + +## 介绍 + +[EventMesh(incubating)](https://github.com/apache/incubator-eventmesh) 是一个动态的云原生事件基础设施. + +## OpenTelemetry 概述 + +OpenTelemetry 是工具、API 和 SDK 的集合。您可以使用它来检测、生成、收集和导出遥测数据(指标、日志和跟踪)以进行分析,以便了解您的软件的性能和行为。 + +## 概述 Prometheus + +使用领先的开源监控解决方案为您的指标和警报提供支持。 + +- 尺寸数据 +- 强大的查询 +- 伟大的可视化 +- 高效存储 +- 操作简单 +- 精准预警 +- 许多客户端库 +- 许多集成 + +## 要求 + +### 功能要求 + +| Requirement ID | Requirement Description | Comments | +| :------------- | ------------------------------------------------------------ | ------------- | +| F-1 | EventMesh users should be able to observe HTTP metrics from Prometheus | Functionality | +| F-2 | EventMesh users should be able to observe TCP metrics from Prometheus | Functionality | + +## 设计 细节 + +使用由提供的儀表儀器 OpenTelemetry 觀察指標存在於 EventMesh 然後導出到 Prometheus. + +1、初始化儀表儀器 + +2、設置 Prometheus 服務器 + +3、创建了不同的指标观察者 + +## 附录 + +### 参考资料 + + diff --git a/docs/zh/desing-document/06-cloudevents.md b/docs/zh/desing-document/06-cloudevents.md new file mode 100644 index 0000000000..2d53e6079e --- /dev/null +++ b/docs/zh/desing-document/06-cloudevents.md @@ -0,0 +1,102 @@ +# CloudEvents 集成 + +## 介绍 + +[CloudEvents](https://github.com/cloudevents/spec) 是一种描述事件数据的格式规范,它提供了跨服务、平台与系统的互操作性。 + +截止至 2021 年 5 月,EventMesh 包含了以下主要组件:`eventmesh-runtime`, `eventmesh-sdk-java` 和 `eventmesh-connector-rocketmq`。 + +对于使用 EventMesh 的用户,`eventmesh-runtime` 可以被部署为微服务来在生产者和消费者间传输用户的事件。 +用户的应用程序可以通过 `eventmesh-sdk-java` 来与 `eventmesh-runtime` 进行交互,即发布或订阅指定主题的事件。 + +EventMesh 的用户非常渴望能得到对 CloudEvents 的支持。有许多理由使得用户倾向于使用集成了 CloudEvents 支持的 SDK: + +- CloudEvents 是一种更为广泛接受和支持的描述事件的方式。目前,`eventmesh-sdk-java` 使用的是 `LiteMessage` 结构 + 来描述事件,其标准化程度较低。 +- CloudEvents 的 Java SDK 有更广泛的分发方式。比如,目前 EventMesh 的用户需要使用 SDK 的 tar 包,或对每个 EventMesh 的 + 发布版本从源码编译。有了 CloudEvents 的支持,用户可以更方便地通过 CloudEvents 的公开分发(比如,配置 Maven)来添加 + EventMesh SDK 依赖项。 +- CloudEvents 的 SDK 支持多种语言。尽管目前 EventMesh 只提供了 Java SDK,但在未来,如果要为更多语言提供支持,将 Java SDK + 与 CloudEvents 绑定的经验将使工作变得容易。 + +## 需求 + +### 功能需求 + +| 需求 ID | 需求描述 | 备注 | +| ------ | ------- | --- | +| F-1 | EventMesh 用户应能使用公共 SDK 依赖项来发布或订阅 CloudEvents 格式的事件 | 功能性 | +| F-2 | EventMesh 用户应能在提供了 CloudEvents 支持的 SDK 中继续使用现有的 EventMesh 客户端功能(如负载均衡) | 功能等价 | +| F-3 | EventMesh 的开发者应不需要付出特别多努力/痛苦来在 `eventmesh-sdk-java` 和提供了 CloudEvents 支持的 SDK 之间同步 | 可维护性 | +| F-4 | EventMesh 支持可插拔的协议,以便开发者整合其他协议(例如:CloudEvents / EventMesh MessageOpenMessage / MQTT...) | 功能性 | +| F-5 | EventMesh 支持统一的 API 以供从/向事件库发布或订阅事件 | 功能性 | + +### 性能需求 + +| 需求 ID | 需求描述 | 备注 | +| ------ | ------- | --- | +| P-1 | 提供了 CloudEvents 支持的 SDK 应具有与目前的 SDK 相近的客户端延迟 | | + +## 设计细节 + +与 CloudEvents 的 Java SDK 绑定(这与 Kafka 已经完成的工作类似,请在附录中的参考资料了解更多细节)是达成上述需求的一种简单方法。 + +### 可插拔协议 + +![可插拔协议](../../images/design-document/cloudevents-pluggable-protocols.png) + +### EventMesh 集成 CloudEvents 进度表 + +#### TCP + +##### SDK 端发布 + +- 在 `package` 首部中添加 CloudEvents 标识符 +- 使用 `CloudEventBuilder` 构造 CloudEvent,并将其放入 `package` 体中 + +##### SDK 端订阅 + +- 在 `ReceiveMsgHook` 接口下添加 `convert` 函数,其用于将 `package` 体转换为具有 `package` 首部标识符的特定协议 +- 不同协议应实现 `ReceiveMsgHook` 接口 + +##### 服务端发布 + +- 设计包含 `decodeMessage` 接口的协议转换 API,其可以把包体转换为 CloudEvent +- 更新 `MessageTransferTask` 下的 `Session.upstreamMsg()`,将入参 `Message` 改为 `CloudEvent`,这使用了 + 上一步的 `decodeMessage` API 来进行对 CloudEvent 的转换 +- 更新 `SessionSender.send()`,将入参 `Message` 改为 `CloudEvent` +- 更新 `MeshMQProducer` API,支持在运行时发送 `CloudEvents` +- 在 `connector-plugin` 中实现支持向 EventStore 中发送 `CloudEvents` + +##### 服务端订阅 + +- 支持将连接器插件中的 `RocketMessage` 改为 `CloudEvent +- 重写 `AsyncMessageListener.consume()` 函数,将入参 `Message` 改为 `CloudEvent` +- 更新 `MeshMQPushConsumer.updateOffset()`,将入参 `Message` 改为 `CloudEvent` +- 更新 `DownStreamMsgContext`,将入参 `Message` 改为 `CloudEvent`,更新 `DownStreamMsgContext.ackMsg` + +#### HTTP + +##### SDK 端发布 + +- 支持 `LiteProducer.publish(cloudEvent)` +- 在 http 请求头中添加 CloudEvents 标识符 + +##### SDK 端订阅 + +##### 服务端发布 + +- 支持根据 `HttpCommand` 首部中的协议类型,通过可插拔的协议插件构造 `HttpCommand.body` +- 支持在消息处理器中发布 CloudEvent + +##### 服务端订阅 + +- 更新 `EventMeshConsumer.subscribe()` +- 更新 `HandleMsgContext`, 将入参 `Message` 改为 `CloudEvent` +- 更新 `AsyncHttpPushRequest.tryHTTPRequest()` + +## 附录 + +### 参考资料 + +- diff --git a/docs/zh/desing-document/08-spi.md b/docs/zh/desing-document/08-spi.md new file mode 100644 index 0000000000..5fb301f408 --- /dev/null +++ b/docs/zh/desing-document/08-spi.md @@ -0,0 +1,111 @@ +# EventMesh SPI + +## 介绍 + +为了提高扩展性,EventMesh通过引入SPI(Service Provider Interface)机制,能够在运行时自动寻找扩展接口的具体实现类,动态加载。 +在EventMesh中,一切扩展点都利用SPI采用插件的实现方式,用户可以通过实现扩展接口,开发自定义的插件,在运行时通过简单的配置,声明式的选择所需要运行的插件。 + +## eventmesh-spi模块 + +SPI相关的代码位于eventmesh-spi模块下,其中主要包括EventMeshExtensionFactory, EventMeshSPI, ExtensionClassLoader这三个类。 + +### EventMeshSPI + +EventMeshSPI是SPI注解,所有需要采用SPI实现扩展的接口都需要使用@EventMeshSPI注解标记。 + +```java +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface EventMeshSPI { + + /** + * If true, the spi instance is singleton + */ + boolean isSingleton() default false; + +} +``` + +这么做的原因是可以通过注解的方式声明接口为SPI扩展接口,提高代码的可读性。同时,@EventMeshSPI注解中包含一个isSingleton属性, +用来声明该扩展接口是否采用单例的实现方式,如果为true,那么该接口的实现类将会使用单例的实现方式,在一个JVM进程中全局唯一。 + +### EventMeshExtensionFactory + +EventMeshExtensionFactory是SPI实现类的获取工厂,包含一个静态方法`getExtension(Class extensionType, String extensionName)`, +接收扩展接口字节码对象和扩展实例名称,用于获取扩展接口的具体实现类。 + +```java +public enum EventMeshExtensionFactory { + ; + /** + * @param extensionType extension plugin class type + * @param extensionName extension instance name + * @param the type of the plugin + * @return plugin instance + */ + public static T getExtension(Class extensionType, String extensionName) { + } +} +``` + +所有需要获取扩展实现的地方都应该通过EventMeshExtensionFactory获取。 + +### ExtensionClassLoader + +ExtensionClassLoader是扩展接口实现类的加载接口,包含两个实现子类MetaInfExtensionClassLoader和JarExtensionClassLoader。 + +```java +/** + * Load extension class + *
    + *
  • {@link MetaInfExtensionClassLoader}
  • + *
  • {@link JarExtensionClassLoader}
  • + *
+ */ +public interface ExtensionClassLoader { + + /** + * load + * + * @param extensionType extension type class + * @param extension type + * @return extension instance name to extension instance class + */ + Map> loadExtensionClass(Class extensionType); +} +``` + +MetaInfExtensionClassLoader用于从classPath直接加载实现类,JarExtensionClassLoader用于从配置目录下通过加载Jar包的方式加载实现类,未来可能还会提供通过从Maven仓库下加载实现类。 + +## SPI使用示例 + +下面以eventmesh-connector-plugin为例,介绍SPI具体的使用过程。 + +首先定义一个eventmesh-connector-api模块,并且定义扩展接口MeshMQProducer。在MeshMQProducer接口上使用@EventMeshSPI注解进行声明,表明该接口是一个SPI扩展接口 + +```java +@EventMeshSPI(isSingleton = false) +public interface MeshMQProducer extends Producer { +... +} +``` + +eventmesh-connector-rocketmq模块中包含采用rocketmq的具体实现方式RocketMQProducerImpl。 + +```java +public class RocketMQProducerImpl implements MeshMQProducer { +... +} +``` + +同时,还需要在eventmesh-connector-rocketmq模块中resource/META-INF/eventmesh目录下创建文件名为SPI接口全限定名的文件 +org.apache.eventmesh.api.producer.Producer + +文件内容为扩展实例名和对应的实例全类名 + +```properties +rocketmq=org.apache.eventmesh.connector.rocketmq.producer.RocketMQProducerImpl +``` + +至此,一个SPI扩展模块就完成了。在使用的时候只需要通过EventMeshExtensionFactory.getExtension(MeshMQProducer.class, “rocketmq”)就可以获取RocketMQProducerImpl实现类。 diff --git a/docs/zh/desing-document/09-event-bridge.md b/docs/zh/desing-document/09-event-bridge.md new file mode 100644 index 0000000000..b74b78e015 --- /dev/null +++ b/docs/zh/desing-document/09-event-bridge.md @@ -0,0 +1,156 @@ +# Event Bridge + +![event-bridge](../../images/eventmesh-bridge.png) + +Event Bridge 可以支持跨mesh集群的消息投递,下面展示这一功能的详细设计与体验步骤 + +![event-bridge-detail](../../images/design-document/event-bridge-detail.png) + +> 注:在本地体验这一功能时需要启动两台eventmesh实例,同时要修改`eventmesh-runtime`目录下的`eventmesh.properties`文件中的端口配置,避免端口冲突。便于下文描述,event-bridge特性按照上图信息进行表述。 + +## 01 远程订阅 + +**描述**:向cluster2 eventmesh发起远程订阅指令,cluster2 eventmesh收到指令后会携带订阅信息调用cluster1 eventmesh的本地订阅接口 + +**URL**: http://{cluster2 address}/eventmesh/subscribe/remote + +**请求方式**:POST + +**请求参数:**application/json 格式 + +| 参数名 | 类型 | 是否必填 | 说明 | +| ------------- | ------ | -------- | ------------------------------------------------------------ | +| url | String | 是 | 标识订阅url信息,暂时无用,后续可移除,目前仅为强校验,实际会被(/eventmesh/bridge/publish)替换 | +| consumerGroup | String | 是 | 标识消费组信息,实际会被cluster2的eventmesh配置信息替换 | +| topic | List | 是 | 标识订阅信息列表 | +| mode | String | 是 | 标识消费模式,分为集群模式和广播模式 | +| topic | String | 是 | 标识订阅的topic | +| type | String | 是 | 标识消费类型,分为同步和异步 | +| remoteMesh | String | 否 | 标识远程mesh地址,优先根据topic从注册中心获取,获取不到使用该字段替换 | + +**请求样例:** + +```json +{ + "url": "http://127.0.0.1:8088/sub/test", + "consumerGroup": "TEST-GROUP", + "topic": [ + { + "mode": "CLUSTERING", + "topic": "TEST-TOPIC-HTTP-ASYNC", + "type": "ASYNC" + } + ], + "remoteMesh" : "http://127.0.0.1:10105/eventmesh/subscribe/local" +} +``` + +## 02 本地订阅 + +**描述**:向cluster2的EventMesh实例发起本地订阅指令,cluster2的EventMesh收到订阅指令后会启动本地监听从event store收下来的消息,并推送给订阅信息中的url。 + +**URL**: http://{cluster2 address}/eventmesh/subscribe/local + +**请求方式**:POST + +**请求参数:**application/json 格式 + +| 参数名 | 类型 | 是否必填 | 说明 | +| ------------- | ------ | -------- | ------------------------------------ | +| url | String | 是 | 标识订阅url信息 | +| consumerGroup | String | 是 | 标识消费组信息 | +| topic | List | 是 | 标识订阅信息列表 | +| mode | String | 是 | 标识消费模式,分为集群模式和广播模式 | +| topic | String | 是 | 标识订阅的topic | +| type | String | 是 | 标识消费类型,分为同步和异步 | + +**请求样例:** + +```JSON +{ + "url": "http://127.0.0.1:8088/sub/test", + "consumerGroup": "TEST-GROUP", + "topic": [ + { + "mode": "CLUSTERING", + "topic": "TEST-TOPIC-HTTP-ASYNC", + "type": "ASYNC" + } + ] +} +``` + +## 03 发送消息 + +**描述**:向cluster1的EventMesh实例发送消息,cluster1的EventMesh收到消息后会发送到event store,再从event store收下来消息推送给cluster2的EventMesh url `/eventmesh/bridge/publish`。 + +**URL**: http://{cluster1 address}/eventmesh/publish/TEST-TOPIC-HTTP-ASYNC + +**请求方式**:POST + +**请求参数:**application/json 格式 + +**请求样例:** + +```json +{ + "name":"test", + "age":"19" +} +``` + +## 04远程去订阅 + +**描述**:向cluster2的EventMesh实例发送去除订阅指令,cluster2的EventMesh收到指令后会发送cluster1的EventMesh,cluster1的EventMesh会本地执行去除订阅 + +**URL**: http://{cluster2 address}/eventmesh/unsubscribe/remote + +**请求方式**:POST + +**请求参数:**application/json 格式 + +| 参数名 | 类型 | 是否必填 | 说明 | +| ------------- | ------ | -------- | ------------------------------------------------------------ | +| url | String | 是 | 标识要去除订阅url信息,暂时无用,后续可移除,目前仅为强校验,实际会被(/eventmesh/bridge/publish)替换 | +| consumerGroup | String | 是 | 标识要去除的消费组信息,实际会使用EventMesh cluster2的group信息替换 | +| topic | List | 是 | 标识订阅topic信息列表 | + +**请求样例:** + +```json +{ + "consumerGroup": "EventMeshTest-consumerGroup", + "url": "http://127.0.0.1:8088/sub/test", + "topic": [ + "TEST-TOPIC-HTTP-ASYNC" + ] +} +``` + +## 05本地去订阅 + +**描述**:向cluster2的EventMesh实例发送去除订阅指令,cluster2的EventMesh收到指令后会本地执行去除订阅 + +**URL**: http://{cluster2 address}/eventmesh/unsubscribe/local + +**请求方式**:POST + +**请求参数:**application/json 格式 + +| 参数名 | 类型 | 是否必填 | 说明 | +| ------------- | ------ | -------- | ---------------------- | +| url | String | 是 | 标识要去除订阅url信息 | +| consumerGroup | String | 是 | 标识要去除的消费组信息 | +| topic | List | 是 | 标识订阅topic信息列表 | + +**请求样例:** + +```json +{ + "consumerGroup": "EventMeshTest-consumerGroup", + "url": "http://127.0.0.1:8088/sub/test", + "topic": [ + "TEST-TOPIC-HTTP-ASYNC" + ] +} +``` \ No newline at end of file diff --git a/docs/zh/desing-document/10-knative-connector.md b/docs/zh/desing-document/10-knative-connector.md new file mode 100644 index 0000000000..ce7d4c52f6 --- /dev/null +++ b/docs/zh/desing-document/10-knative-connector.md @@ -0,0 +1,91 @@ +# Knative Connector插件 + +## 准备 +### 创建Knative Source和Sink +我们使用 *cloudevents-player* [Knative服务](https://knative.dev/docs/serving/)作为例子。如果您不知道如何创建 *cloudevents-player* Knative服务作为source和sink,请按照这个[链接](https://knative.dev/docs/getting-started/first-source/#creating-your-first-source)的步骤进行创建。 + +### EventMesh配置文件 +- 将以下配置加入 [eventmesh-starter/build.gradle](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-starter/build.gradle) 文件 +```bash +plugins { + id 'application' +} + +application { + mainClass = project.hasProperty("mainClass") ? project.getProperty("mainClass") : 'org.apache.eventmesh.starter.StartUp' + applicationDefaultJvmArgs = [ + '-Dlog4j.configurationFile=../eventmesh-runtime/conf/log4j2.xml', '-Deventmesh.log.home=../eventmesh-runtime/logs', '-Deventmesh.home=../eventmesh-runtime', '-DconfPath=../eventmesh-runtime/conf' + ] +} + +dependencies { + implementation project(":eventmesh-connector-plugin:eventmesh-connector-knative") + implementation project(":eventmesh-runtime") +} +``` +- 将以下配置加入 [eventmesh-examples/build.gradle](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-examples/build.gradle)文件 +```bash +plugins { + id 'application' +} + +application { + mainClass = project.hasProperty("mainClass") ? project.getProperty("mainClass") : 'NULL' +} +``` +- 在 [eventmesh-runtime/conf/eventmesh.properties](https://github.com/pchengma/incubator-eventmesh/blob/master/eventmesh-runtime/conf/eventmesh.properties) 文件中设置```eventMesh.connector.plugin.type=knative```变量 + +## 演示 +### Knative发布事件消息/EventMesh订阅 +#### 步骤1:启动一台EventMesh服务器 +```bash +$ cd eventmesh-starter +$ ../gradlew -PmainClass=org.apache.eventmesh.starter.StartUp run +``` + +#### 步骤2:从Knative Source发布一条消息 +```bash +$ curl -i http://cloudevents-player.default.127.0.0.1.sslip.io -H "Content-Type: application/json" -H "Ce-Id: 123456789" -H "Ce-Specversion: 1.0" -H "Ce-Type: some-type" -H "Ce-Source: command-line" -d '{"msg":"Hello CloudEvents!"}' +``` + +#### 步骤3:从EventMesh订阅 +- 在 [ExampleConstants.java](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-examples/src/main/java/org/apache/eventmesh/common/ExampleConstants.java) 文件中设置 ```public static final String EVENTMESH_HTTP_ASYNC_TEST_TOPIC = "messages";```变量 +```bash +$ cd eventmesh-examples +$ ../gradlew -PmainClass=org.apache.eventmesh.http.demo.sub.SpringBootDemoApplication run +``` +#### 预期结果 +以下```data```为```Hello CloudEvents!```的消息将会打印在EventMesh服务器的控制台上。 +```bash +2022-09-05 16:37:58,237 INFO [eventMesh-clientManage-] DefaultConsumer(DefaultConsumer.java:60) - \ +[{"event":{"attributes":{"datacontenttype":"application/json","id":"123456789","mediaType":"application/json",\ +"source":"command-line","specversion":"1.0","type":"some-type"},"data":{"msg":"Hello CloudEvents!"},"extensions":{}},\ +"id":"123456789","receivedAt":"2022-09-05T10:37:49.537658+02:00[Europe/Madrid]","type":"RECEIVED"}] +``` + +### EventMessh发布事件消息/Knative订阅 +#### 步骤1:启动一台EventMesh服务器 +```bash +$ cd eventmesh-starter +$ ../gradlew -PmainClass=org.apache.eventmesh.starter.StartUp run +``` + +#### 步骤2:从EventMesh发布一条消息 +我们用Knative Connector的测试程序来演示这个功能。 +```bash +$ cd eventmesh-connector-plugin/eventmesh-connector-knative +$ ../../gradlew clean test --tests KnativeProducerImplTest.testPublish +``` + +#### 步骤3:从Knative订阅 +```bash +$ curl http://cloudevents-player.default.127.0.0.1.sslip.io/messages +``` + +#### 预期结果 +以下```data```为```Hello Knative from EventMesh!```的消息将会打印在EventMesh服务器的控制台上。 +```bash +2022-09-05 16:52:41,633 INFO [eventMesh-clientManage-] DefaultConsumer(DefaultConsumer.java:60) - \ +[{"event":{"attributes":{"datacontenttype":"application/json","id":"1234","mediaType":"application/json",\ +"source":"java-client","specversion":"1.0","type":"some-type"},"data":{"msg":["Hello Knative from EventMesh!"]},"extensions":{}},"id":"1234","receivedAt":"2022-09-05T10:52:32.999273+02:00[Europe/Madrid]","type":"RECEIVED"}] +``` \ No newline at end of file diff --git a/docs/zh/desing-document/11-prometheus.md b/docs/zh/desing-document/11-prometheus.md new file mode 100644 index 0000000000..067cd00abf --- /dev/null +++ b/docs/zh/desing-document/11-prometheus.md @@ -0,0 +1,46 @@ +# 通过 Prometheus 观察 Metrics + +## 下载 Prometheus + +官网:https://prometheus.io/ + +本地下载Prometheus:https://prometheus.io/download/ + +选择自己电脑对应的版本下载并解压缩 + +![Prometheus-download](../../images/Prometheus-download.png) + +### 2、在prometheus.yml中添加配置 + +如果你是Prometheus的新手,可以直接复制eventmesh-runtime/conf/prometheus.yml替换 + +例如:这是win-64的下载后的样子: + +![prometheus-yml](../../images/prometheus-yml.png) + +替换红框中的文件 + +如果你十分了解Prometheus,可以自行配置,eventmesh默认的导出的端口为19090。 + +ps:如果需要更换端口的话,请修改eventmesh-runtime/conf/eventmesh.properties中的 + +```properties +#prometheusPort +eventMesh.metrics.prometheus.port=19090 +``` + +## 运行 Prometheus 和 EventMesh + +双击Prometheus.exe运行 + +运行eventmesh-starter(参考[eventmesh-runtime-quickstart](eventmesh-runtime-quickstart.md)) + +运行eventmesh-example(参考[eventmesh-sdk-java-quickstart](eventmesh-sdk-java-quickstart.md)) + +打开浏览器访问:http://localhost:9090/ + +### 输入想观察的 Metrics + +输入’**eventmesh_**‘ 就会出现相关的指标的提示 + +![promethus-search](../../images/promethus-search.png) diff --git a/docs/zh/desing-document/12-zipkin.md b/docs/zh/desing-document/12-zipkin.md new file mode 100644 index 0000000000..913ee056cc --- /dev/null +++ b/docs/zh/desing-document/12-zipkin.md @@ -0,0 +1,49 @@ +# 通过 Zipkin 观察 Trace + +### 1、下载和运行Zipkin + +请参考https://zipkin.io/pages/quickstart.html + + + +### 2、运行eventmesh + +运行eventmesh-starter(参考[eventmesh-runtime-quickstart](eventmesh-runtime-quickstart.md)) + +运行eventmesh-example(参考[eventmesh-sdk-java-quickstart](eventmesh-sdk-java-quickstart.md)) + + + +### 3、相关的设置 + +eventmesh-runtime/conf/eventmesh.properties中: + +默认的exporter是log,需要手动改成Zipkin + +```properties +#trace exporter +eventmesh.trace.exporter.type=Zipkin +``` +下面是关于Zipkin的各种配置 +```properties +#set the maximum batch size to use +eventmesh.trace.exporter.max.export.size=512 +#set the queue size. This must be >= the export batch size +eventmesh.trace.exporter.max.queue.size=2048 +#set the max amount of time an export can run before getting(TimeUnit=SECONDS) +eventmesh.trace.exporter.export.timeout=30 +#set time between two different exports(TimeUnit=SECONDS) +eventmesh.trace.exporter.export.interval=5 + +#zipkin +eventmesh.trace.export.zipkin.ip=localhost +eventmesh.trace.export.zipkin.port=9411 +``` + +以上都是相关的配置,如果你十分熟悉Zipkin的话可以自行修改。 + + + +### 4、观察 + +浏览器打开: **localhost:9411** diff --git a/docs/zh/desing-document/13-jaeger.md b/docs/zh/desing-document/13-jaeger.md new file mode 100644 index 0000000000..9ac0269342 --- /dev/null +++ b/docs/zh/desing-document/13-jaeger.md @@ -0,0 +1,44 @@ +# 通过 Jaeger 观察 Trace + +## Jaeger + +[Jaeger](https://www.jaegertracing.io/) 是 [Uber](https://uber.github.io/) 开发的分布式跟踪系统,现已成为 [CNCF](https://cncf.io/) 开源项目,其灵感来源于 Google 的 [Dapper](https://research.google.com/pubs/pub36356.html) 和 Twitter 的 [Zipkin](https://zipkin.io/),用于监控基于微服务的分布式系统。 + +Jaeger 的安装可以参考[官方文档](https://www.jaegertracing.io/docs/latest/getting-started/),推荐使用官方的 Docker 镜像 `jaegertracing/all-in-one` 来快速搭建环境进行测试。 + +## 配置 + +为了启用 EventMesh Runtime 的 trace exporter,请将 `conf/eventmesh.properties` 文件中的 `eventMesh.server.trace.enabled` 字段设置为 true。 + +```conf +# Trace plugin +eventMesh.server.trace.enabled=true +eventMesh.trace.plugin=jaeger +``` + +为了定义 trace exporter 的行为,如超时时间或导出间隔,请编辑 `exporter.properties` 文件。 + +```conf +# Set the maximum batch size to use +eventmesh.trace.max.export.size=512 +# Set the queue size. This must be >= the export batch size +eventmesh.trace.max.queue.size=2048 +# Set the max amount of time an export can run before getting(TimeUnit=SECONDS) +eventmesh.trace.export.timeout=30 +# Set time between two different exports (TimeUnit=SECONDS) +eventmesh.trace.export.interval=5 +``` + +为了将导出的 trace 数据发送到 Jaeger,请编辑 `conf/jaeger.properties` 文件中的 `eventmesh.trace.jaeger.ip` 和 `eventmesh.trace.jaeger.port` 字段,来匹配 Jaeger 服务器的配置。 + +```conf +# Jaeger's IP and Port +eventmesh.trace.jaeger.ip=localhost +eventmesh.trace.jaeger.port=14250 +``` + +## 从 Zipkin 迁移 + +Jaeger 采集器服务暴露了与 Zipkin 兼容的 REST API,`/api/v1/spans` 可以接收 Thrift 和 JSON,`/api/v2/spans` 可以接收 JSON 和 Proto。 + +因此你也可以使用 `eventmesh-trace-zipkin` 插件来通过 Jaeger 观察 trace,具体配置细节请参考 `eventmesh-trace-zipkin` 的文档。默认情况下这个特性在 Jaeger 中是关闭的,可以通过 `--collector.zipkin.host-port=:9411` 启用。 \ No newline at end of file diff --git a/docs/zh/desing-document/_category_.json b/docs/zh/desing-document/_category_.json new file mode 100644 index 0000000000..95b7eed067 --- /dev/null +++ b/docs/zh/desing-document/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Documentation", + "collapsed": false +} diff --git a/docs/zh/desing-document/https.md b/docs/zh/desing-document/https.md new file mode 100644 index 0000000000..a100ba3977 --- /dev/null +++ b/docs/zh/desing-document/https.md @@ -0,0 +1,32 @@ +# HTTPS + +1.在eventmesh-runtime 中配置 + +``` +eventMesh.properties(添加如下配置) +eventMesh.server.useTls.enabled=true //默认值 false + + +config env varible +-Dssl.server.protocol=TLSv1.1 //默认值 TLSv1.1 +-Dssl.server.cer=sChat2.jks //把文件放到启动脚本start.sh 指定的conPath目录下 +-Dssl.server.pass=sNetty +``` + +2.在eventmesh-sdk-java 中配置 + +``` +//创建producer +LiteClientConfig eventMeshHttpClientConfig = new eventMeshHttpClientConfig(); +... + +//设置开启TLS +eventMeshHttpClientConfig.setUseTls(true); +LiteProducer producer = new LiteProducer(eventMeshHttpClientConfig); + + +//配置环境变量 +-Dssl.client.protocol=TLSv1.1 //默认值 TLSv1.1 +-Dssl.client.cer=sChat2.jks //把文件放到应用指定的conPath目录下 +-Dssl.client.pass=sNetty +``` diff --git a/docs/zh/desing-document/webhook.md b/docs/zh/desing-document/webhook.md new file mode 100644 index 0000000000..aa4d497f54 --- /dev/null +++ b/docs/zh/desing-document/webhook.md @@ -0,0 +1,268 @@ + + +## webhook使用流程 +#### 第一步:在eventmesh配置webhook相关信息并且启动 + +##### 配置说明 +``` +# 是否启动webhook admin服务 +eventMesh.webHook.admin.start=true + +# webhook事件配置存储模式。目前只支持file与nacos +eventMesh.webHook.operationMode=file +# 文件存储模式的文件存放路径,如果写上#{eventMeshHome},在eventMesh根目录 +eventMesh.webHook.fileMode.filePath= #{eventMeshHome}/webhook + +# nacos存储模式,配置命名规则是eventMesh.webHook.nacosMode.{nacos 原生配置key} 具体的配置请看 [nacos github api](https://github.com/alibaba/nacos/blob/develop/api/src/main/java/com/alibaba/nacos/api/SystemPropertyKeyConst.java) +## nacos的地址 +eventMesh.webHook.nacosMode.serverAddr=127.0.0.1:8848 + +# webhook eventcloud 发送模式。与eventMesh.connector.plugin.type 配置一样 +eventMesh.webHook.producer.connector=standalone +``` + +#### 第二步:添加webhook配置信息 +配置信息说明 +```java + /** + * 厂商调用的path。厂商事件调用地址、 [http or https ]://[域名 or IP 【厂商可以被调用】]:[端口]/webhook/[callbackPath] + * 比如:http://127.0.0.1:10504/webhook/test/event 需要把全完url填入厂商调用输入中 + * callbackPath 是唯一 + * manufacturer callback path + */ + private String callbackPath; + + /** + * 厂商的名字 + * manufacturer name ,like github + */ + private String manufacturerName; + + /** + * 厂商的事件名 + * webhook event name ,like rep-push + */ + private String manufacturerEventName; + + /** + * + * http header content type + */ + private String contentType = "application/json"; + + /** + * 说明 + * description of this WebHookConfig + */ + private String description; + + /** + * 有一些厂商使用验签方式, + * secret key ,for authentication + */ + private String secret; + + /** + * 有一些厂商使用验签方式,使用账户密码方式 + * userName ,for HTTP authentication + */ + private String userName; + + /** + * 有一些厂商使用验签方式,使用账户密码方式 + * password ,for HTTP authentication + */ + private String password; + + + + /** + * 事件发送到那个topic + * roll out event name ,like topic to mq + */ + private String cloudEventName; + + /** + * roll out data format -> CloudEvent serialization mode + * If HTTP protocol is used, the request header contentType needs to be marked + */ + private String dataContentType = "application/json";; + + /** + * source of event + */ + private String cloudEventSource; + + /** + * cloudEvent事件对象唯一标识符识别方式,uuid或者manufacturerEventId(厂商id) + * id of cloudEvent ,like uuid/manufacturerEventId + */ + private String cloudEventIdGenerateMode; + +``` + +##### 添加接口 +路径: /webhook/insertWebHookConfig +方法: POST +contentType: application/json + +输入参数: +| 字段 | 说明 | 类型 | 必须 | 默认值 | +| -- | -- | -- | -- | -- | +| callbackPath | 调用地址,唯一地址 | string | 是 | null | +| manufacturerName | 厂商名 | string | 是 | null | +| manufacturerEventName | 厂商事件名 | string | 是 | null | +| contentType | http connettype | string | 否 | application/json | +| description | 配置说明 | string | 否 | null | +| secret | 验签密钥 | string | 否 | null | +| userName | 用户名 | string | 否 | null | +| password | 用户密码 | string | 否 | null | +| cloudEventName | 事件名() | string | 是 | null | +| cloudEventSource | 事件来源可以填写 | string | 是 | null | +| cloudEventIdGenerateMode | cloudEvent事件对象唯一标识符识别方式,uuid或者manufacturerEventId(厂商id) | string | 否 | manufacturerEventId | + +列子: +```json + +{ + "callbackPath":"/webhook/github/eventmesh/all", + "manufacturerName":"github", + "manufacturerEventName":"all", + "secret":"eventmesh", + "cloudEventName":"github-eventmesh", + "cloudEventSource":"github" +} + +``` +输出参数:1 成功,0失败 + +##### 删除接口 +路径: /webhook/deleteWebHookConfig +方法: POST +contentType: application/json + +输入参数: +| 字段 | 说明 | 类型 | 必须 | 默认值 | +| -- | -- | -- | -- | -- | +| callbackPath | 调用地址,唯一地址 | string | 是 | null | + + +列子: + +```json + +{ + "callbackPath":"/webhook/github/eventmesh/all" +} + +``` + + +输出参数:1 成功,0失败 + +##### 通过callbackPath查询WebHookConfig +路径: /webhook/queryWebHookConfigById +方法: POST +contentType: application/json + +输入参数: +| 字段 | 说明 | 类型 | 必须 | 默认值 | +| -- | -- | -- | -- | -- | +| callbackPath | 调用地址,唯一地址 | string | 是 | null | + + +列子: + +```json + +{ + "callbackPath":"/webhook/github/eventmesh/all" +} + +``` + + +输出参数: +| 字段 | 说明 | 类型 | 必须 | 默认值 | +| -- | -- | -- | -- | -- | +| callbackPath | 调用地址,唯一地址 | string | 是 | null | +| manufacturerName | 厂商名 | string | 是 | null | +| manufacturerEventName | 厂商事件名 | string | 是 | null | +| contentType | http connettype | string | 否 | application/json | +| description | 配置说明 | string | 否 | null | +| secret | 验签密钥 | string | 否 | null | +| userName | 用户名 | string | 否 | null | +| password | 用户密码 | string | 否 | null | +| cloudEventName | 事件名() | string | 是 | null | +| cloudEventSource | 事件来源可以填写 | string | 是 | null | +| cloudEventIdGenerateMode | cloudEvent事件对象唯一标识符识别方式,uuid或者manufacturerEventId(厂商id) | string | 否 | manufacturerEventId | + + +##### 通过manufacturer查询WebHookConfig列表 +路径: /webhook/queryWebHookConfigByManufacturer +方法: POST +contentType: application/json + +输入参数: +| 字段 | 说明 | 类型 | 必须 | 默认值 | +| -- | -- | -- | -- | -- | +| manufacturerName | 厂商名 | string | 是 | null | + + +列子: + +```json + +{ + "manufacturerName":"github" +} + +``` + + +输出参数: +| 字段 | 说明 | 类型 | 必须 | 默认值 | +| -- | -- | -- | -- | -- | +| callbackPath | 调用地址,唯一地址 | string | 是 | null | +| manufacturerName | 厂商名 | string | 是 | null | +| manufacturerEventName | 厂商事件名 | string | 是 | null | +| contentType | http connettype | string | 否 | application/json | +| description | 配置说明 | string | 否 | null | +| secret | 验签密钥 | string | 否 | null | +| userName | 用户名 | string | 否 | null | +| password | 用户密码 | string | 否 | null | +| cloudEventName | 事件名() | string | 是 | null | +| cloudEventSource | 事件来源可以填写 | string | 是 | null | +| cloudEventIdGenerateMode | cloudEvent事件对象唯一标识符识别方式,uuid或者manufacturerEventId(厂商id) | string | 否 | manufacturerEventId | + + +#### 第三步:查看配置是否成功 +1. file存储模式。请到eventMesh.webHook.fileMode.filePath 目录下查看。文件名为callbackPath转移后的 +2. nacos存储模式。请到eventMesh.webHook.nacosMode.serverAddr 配置的nacos服务去看 + +#### 第四步:配置cloudevent的消费者 + + +#### 第五步:在厂商配置webhook相关信息 +> 厂商操作请看【厂商webhook操作说明】 + + +## 厂商webhook操作说明 +### github 注册 +#### 第一步:进入对应的项目 +#### 第二步:点击setting +![](../../images/design-document/webhook/webhook-github-setting.png) +#### 第三步:点击Webhooks +![](../../images/design-document/webhook/webhook-github-webhooks.png) +#### 第四步:点击 Add webhook +![](../../images/design-document/webhook/webhook-github-add.png) +#### 第五步: 填写webhook信息 +![](../../images/design-document/webhook/webhook-github-info.png) + +Payload URL: 服务地址以及pahts。[http or https ]://[域名 or IP 【厂商可以被调用】]:[端口]/webhook/[callbackPath] +Content type:http header content type +secret: 验签字符串 + + + + diff --git a/docs/zh/instruction/00-eclipse.md b/docs/zh/instruction/00-eclipse.md new file mode 100644 index 0000000000..27ded49524 --- /dev/null +++ b/docs/zh/instruction/00-eclipse.md @@ -0,0 +1,33 @@ +# eventMesh 导入Eclipse 快速入门说明 + +### 依赖 + +``` +64位JDK 1.8+; +Gradle至少为7.0, 推荐 7.0.* +eclipse 已安装gradle插件或者eclipse自带gradle插件 +``` + +### 下载源码 +git init + +git clone https://github.com/apache/incubator-eventmesh.git + +### 项目编译eclipse环境 + +打开命令行终端,运行gradlew cleanEclipse eclipse + +### 配置修改 +修改工程名称和settings.gradle 配置文件参数rootProject.name 参数一致 + +### 修改eclipse.init配置文件,配置lombok以1.18.8版本为例 +-javaagent:lombok-1.18.8.jar +-XBootclasspath/a:lombok-1.18.8.jar + +### 202106版本eclipse,eclipse.init增加配置参数 +--illegal-access=permit + + +### 导入gradle +打开eclipse,导入gradle项目到IDE里 + diff --git a/docs/zh/instruction/01-store-with-docker.md b/docs/zh/instruction/01-store-with-docker.md new file mode 100644 index 0000000000..539c81cd03 --- /dev/null +++ b/docs/zh/instruction/01-store-with-docker.md @@ -0,0 +1,40 @@ +# eventmesh-store 快速入门说明 + +## 依赖 + +``` +建议使用64位操作系统,建议使用Linux/Unix; +64位JDK 1.8+; +Gradle至少为7.0, 推荐7.0.* +4g+可用磁盘用于eventmesh-store服务器 +eventmesh在非standalone模式下,依赖RocketMQ作为存储层;若采用standalone模式,则可跳过该步,直接进行runtime的部署 +``` + +## 部署 +在命令行输入如下命令直接从 docker hub 上获取 RocketMQ 镜像: + +```shell +#获取 namesrv 镜像 +sudo docker pull rocketmqinc/rocketmq-namesrv:4.5.0-alpine +#获取 broker 镜像 +sudo docker pull rocketmqinc/rocketmq-broker:4.5.0-alpine +``` + +在命令行输入以下命令运行namerv容器和broker容器 + +```shell +#运行 namerv 容器 +sudo docker run -d -p 9876:9876 -v `pwd`/data/namesrv/logs:/root/logs -v `pwd`/data/namesrv/store:/root/store --name rmqnamesrv rocketmqinc/rocketmq-namesrv:4.5.0-alpine sh mqnamesrv + +#运行 broker 容器 +sudo docker run -d -p 10911:10911 -p 10909:10909 -v `pwd`/data/broker/logs:/root/logs -v `pwd`/data/broker/store:/root/store --name rmqbroker --link rmqnamesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" rocketmqinc/rocketmq-broker:4.5.0-alpine sh mqbroker -c ../conf/broker.conf +``` + +请注意 **rocketmq-broker ip** 是 **pod ip**, 如果你想修改这个ip, 可以通过挂载容器中 **broker.conf** 文件的方式并修改文件中的 **brokerIP1** 配置项为自定义值 + + +至此eventmesh-store的部署已完成,请转至下一步完成 [eventmesh-runtime](https://github.com/apache/incubator-eventmesh/blob/master/docs/zh/instruction/02-runtime-with-docker.md) 的部署 + + +## 参考 +关于RocketMQ的其他更多资料,请参考 diff --git a/docs/zh/instruction/01-store.md b/docs/zh/instruction/01-store.md new file mode 100644 index 0000000000..7317e3ad87 --- /dev/null +++ b/docs/zh/instruction/01-store.md @@ -0,0 +1,51 @@ +# eventmesh-store 快速入门说明 + +## 依赖 + +``` +建议使用64位操作系统,建议使用Linux/Unix; +64位JDK 1.8+; +Gradle至少为7.0, 推荐7.0.* +4g+可用磁盘用于eventmesh-store服务器 +eventmesh在非standalone模式下,依赖RocketMQ作为存储层;若采用standalone模式,则可跳过该步,直接进行runtime的部署 +``` + + +## 下载 + +从[RocketMQ官方网站](https://rocketmq.apache.org/dowloading/releases/) 下载Binary代码(推荐使用4.9.*版本),这里以4.9.2为例 + +``` +unzip rocketmq-all-4.9.2-bin-release.zip +cd rocketmq-4.9.2/ +``` + + +## 部署 + +- #### 启动Name Server + +``` +nohup sh bin/mqnamesrv & +tail -f ~/logs/rocketmqlogs/namesrv.log +``` + +如果在看到The Name Server boot success...,则说明Name Server启动成功 + +- #### 启动Broker + +``` +nohup sh bin/mqbroker -n localhost:9876 & +tail -f ~/logs/rocketmqlogs/broker.log +``` + +如果在看到The broker boot success...,则说明Broker启动成功 + +至此eventmesh-store的部署已完成,请转至下一步完成 [eventmesh-runtime](https://github.com/apache/incubator-eventmesh/blob/master/docs/zh/instruction/02-runtime.md) 的部署 + + +## 参考 +关于RocketMQ的其他更多资料,请参考 + + + diff --git a/docs/zh/instruction/02-runtime-with-docker.md b/docs/zh/instruction/02-runtime-with-docker.md new file mode 100644 index 0000000000..640bd59376 --- /dev/null +++ b/docs/zh/instruction/02-runtime-with-docker.md @@ -0,0 +1,149 @@ +# 使用 Docker 快速入门 EventMesh(暂时只支持到1.4.0版本) + +本篇快速入门将详细介绍使用 docker 部署 EventMesh,以 RocketMQ 作为对接的中间件。 + +可选语言: [英文版本](../../en/instructions/eventmesh-runtime-quickstart-with-docker.md),[中文版本](02-runtime-with-docker.md)。 + +## 前提 + +1. 建议使用64位的 linux 系统; +2. 请预先安装 Docker Engine。 Docker 的安装过程可以参考 [docker 官方文档](https://docs.docker.com/engine/install/); +3. 建议掌握基础的 docker 概念和命令行,例如注册中心、挂载等等。不过这不是必须的,因为本次操作所需的命令都已为您列出; +4. 若您选择非standalone模式,请确保 [RocketMQ 已成功启动](https://rocketmq.apache.org/docs/quick-start/) 并且可以使用 ip 地址访问到;若您选择standalone模式,则无需启动 RocketMQ 。 + +## 获取 EventMesh 镜像 + +首先,你可以打开一个命令行,并且使用下面的 ```pull``` 命令从 [Docker Hub](https://registry.hub.docker.com/r/eventmesh/eventmesh/tags) 中下载[最新发布的 EventMesh](https://eventmesh.apache.org/events/release-notes/v1.3.0/) 。 + +```shell +sudo docker pull eventmesh/eventmesh:v1.4.0 +``` + +您可以使用以下命令列出并查看本地已有的镜像。 + +```shell +sudo docker images +``` + +如果终端显示如下所示的镜像信息,则说明 EventMesh 镜像已经成功下载到本地。 + +```shell +REPOSITORY TAG IMAGE ID CREATED SIZE +eventmesh/eventmesh v1.4.0 6e2964599c78 3 months ago 936.73 MB +``` + +## 创建配置文件 + +在根据 EventMesh 镜像运行对应容器之前,你需要创建两个配置文件,分别是:```eventMesh.properties``` 和 ```rocketmq-client.properties```。 + +首先,你需要使用下面的命令创建这两个文件。 + +```shell +sudo mkdir -p /data/eventmesh/rocketmq/conf +cd /data/eventmesh/rocketmq/conf +sudo touch eventmesh.properties +sudo touch rocketmq-client.properties +``` + +### 配置 eventMesh.properties + +这个配置文件中包含 EventMesh 运行时环境和集成进来的其他插件所需的参数。 + +使用下面的 ```vim``` 命令编辑 ```eventmesh.properties```。 + +```shell +sudo vim eventmesh.properties +``` + +你可以直接将 GitHub 仓库中的对应配置文件中的内容复制过来,链接为: 。 + +请检查配置文件里的默认端口是否已被占用,如果被占用请修改成未被占用的端口: + +| 属性 | 默认值 | 备注 | +|----------------------------|-------|----------------------------| +| eventMesh.server.http.port | 10105 | EventMesh http server port | +| eventMesh.server.tcp.port | 10000 | EventMesh tcp server port | +| eventMesh.server.grpc.port | 10205 | EventMesh grpc server port | + +### 配置 rocketmq-client.properties + +这个配置文件中包含 RocketMQ nameserver 的信息。 + +使用下面的 ```vim``` 命令编辑 ```rocketmq-client.properties```。 + +```shell +sudo vim rocketmq-client.properties +``` + +你可以直接将 GitHub 仓库中的对应配置文件中的内容复制过来,链接为: 。请注意,如果您正在运行的 namesetver 地址不是配置文件中的默认值,请将其修改为实际正在运行的nameserver地址。 + +请检查配置文件里的默认namesrvAddr是否已被占用,如果被占用请修改成未被占用的地址: + +| 属性 | 默认值 | 备注 | +|---------------------------------------|-------------------------------|----------------------------------| +| eventMesh.server.rocketmq.namesrvAddr | 127.0.0.1:9876;127.0.0.1:9876 | RocketMQ namesrv default address | + +## 运行 EventMesh + +现在你就可以开始根据下载好的 EventMesh 镜像运行容器了。 + +使用到的命令是 ```docker run```,有以下两点内容需要格外注意。 + +1. 绑定容器端口和宿主机端口:使用 ```docker run``` 的 ```-p``` 选项。 +2. 将宿主机中的两份配置文件挂在到容器中:使用 ```docker run``` 的 ```-v``` 选项。 + +综合一下,对应的启动命令为: + +```shell +sudo docker run -d \ + -p 10000:10000 -p 10105:10105 \ + -v /data/eventmesh/rocketmq/conf/eventMesh.properties:/data/app/eventmesh/conf/eventMesh.properties \ + -v /data/eventmesh/rocketmq/conf/rocketmq-client.properties:/data/app/eventmesh/conf/rocketmq-client.properties \ + eventmesh/eventmesh:v1.4.0 +``` + +如果运行命令之后看到新输出一行字符串,那么运行 EventMesh 镜像的容器就启动成功了。 + +接下来,你可以使用下面的命令查看容器的状态。 + +```shell +sudo docker ps +``` + +如果成功的话,你会看到终端打印出了如下所示容器的信息,其中就有运行 EventMesh 镜像的容器。 + +```shell +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +d1e1a335d4a9 eventmesh/eventmesh:v1.4.0 "/bin/sh -c 'sh star…" About a minute ago Up About a minute 0.0.0.0:10000->10000/tcp, :::10000->10000/tcp, 0.0.0.0:10105->10105/tcp, :::10105->10105/tcp focused_bartik +``` + +从这个信息中可以看出,```container id``` 是 ```d1e1a335d4a9```,```name``` 是 ```focused_bartik```,它们都可以用来唯一标识这个容器。**注意**:在你的电脑中,它们的值可能跟这里的不同。 + +## 管理 EventMesh 容器 + +在成功的运行了 EventMesh 容器后,你可以通过进入容器、查看日志、删除容器等方式管理容器。 + +**进入容器** 命令示例: + +```shell +sudo docker exec -it [your container id or name] /bin/bash +``` + +在容器中 **查看日志** 命令示例: + +```shell +cd ../logs +tail -f eventmesh.out +``` + +**删除容器** 命令示例: + +```shell +sudo docker rm -f [your container id or name] +``` + +## 探索更多 + +现在 EventMesh 已经通过容器运行了,你可以参考 [```eventmesh-examples``` 模块](https://github.com/apache/incubator-eventmesh/tree/master/eventmesh-examples) 编写并测试自己的代码了。 + +希望你享受这个过程并获得更多收获! diff --git a/docs/zh/instruction/02-runtime.md b/docs/zh/instruction/02-runtime.md new file mode 100644 index 0000000000..845f1ccf63 --- /dev/null +++ b/docs/zh/instruction/02-runtime.md @@ -0,0 +1,114 @@ +# Eventmesh-runtime 快速入门说明 + + +## 1 本地构建运行 + +### 1.1 依赖 + +``` +建议使用64位操作系统,建议使用Linux / Unix; +64位JDK 1.8+; +Gradle至少为7.0, 推荐 7.0.* +``` + +### 1.2 下载源码 + +在 [EventMesh download](https://eventmesh.apache.org/download) 页面选择1.5.0版本的 Source Code 进行下载并解压, 您将获得**apache-eventmesh-1.5.0-incubating-src** + + +### 1.3 本地启动 + +**1.3.1 项目结构说明:** + +- eventmesh-common : eventmesh公共类与方法模块 +- eventmesh-connector-api : eventmesh connector插件接口定义模块 +- eventmesh-connector-plugin : eventmesh connector插件模块 +- eventmesh-runtime : eventmesh运行时模块 +- eventmesh-sdk-java : eventmesh java客户端sdk +- eventmesh-starter : eventmesh本地启动运行项目入口 +- eventmesh-spi : eventmesh SPI加载模块 + +> 注:插件模块遵循 eventmesh 定义的SPI规范, 自定义的SPI接口需要使用注解 @EventMeshSPI 标识. +> 插件实例需要在对应模块中的 /main/resources/META-INF/eventmesh 下配置相关接口与实现类的映射文件,文件名为SPI接口全类名. +> 文件内容为插件实例名到插件实例的映射, 具体可以参考 eventmesh-connector-rocketmq 插件模块 + +**1.3.2 插件说明** + +***1.3.2.1 安装插件*** + +有两种方式安装插件 + +- classpath加载:本地开发可以通过在 eventmesh-starter 模块 build.gradle 中进行声明,例如声明使用 rocketmq 插件 + +```gradle + implementation project(":eventmesh-connector-plugin:eventmesh-connector-rocketmq") +``` + +- 文件加载:通过将插件安装到插件目录,EventMesh 在运行时会根据条件自动加载插件目录下的插件,可以通过执行以下命令安装插件 + +```shell +./gradlew clean jar dist && ./gradlew installPlugin +``` + +***1.3.2.2 使用插件*** + +EventMesh 会默认加载 dist/plugin 目录下的插件,可以通过`-DeventMeshPluginDir=your_plugin_directory`来改变插件目录。运行时需要使用的插件实例可以在 +`confPath`目录下面的`eventmesh.properties`中进行配置。例如通过以下设置声明在运行时使用rocketmq插件。 + +```properties +#connector plugin +eventMesh.connector.plugin.type=rocketmq +``` + +**1.3.3 配置VM启动参数** + +```properties +-Dlog4j.configurationFile=eventmesh-runtime/conf/log4j2.xml +-Deventmesh.log.home=eventmesh-runtime/logs +-Deventmesh.home=eventmesh-runtime +-DconfPath=eventmesh-runtime/conf +``` + +> 注:如果操作系统为Windows, 可能需要将文件分隔符换成\ + +**1.3.4 启动运行** + +``` +运行org.apache.eventmesh.starter.StartUp的主要方法 +``` + +## 2 远程部署 + +### 2.1 依赖 + +``` +建议使用64位操作系统,建议使用Linux / Unix; +64位JDK 1.8+; +Gradle至少为7.0, 推荐 7.0.* +``` + +### 2.2 下载 + +在 [EventMesh download](https://eventmesh.apache.org/download) 页面选择1.5.0版本的 Binary Distribution 进行下载, 您将获得**apache-eventmesh-1.5.0-incubating-bin.tar.gz** + + +### 2.3 部署 + +- 部署eventmesh-runtime + +```$ xslt +# 解压 apache-eventmesh-1.5.0-incubating-bin.tar.gz +tar -zxvf apache-eventmesh-1.5.0-incubating-bin.tar.gz +cd apache-eventmesh-1.5.0-incubating + +# 配置 eventMesh.properties +vim conf/eventMesh.properties + +# 启动EventMesh +cd bin +sh start.sh +``` + +如果看到"EventMeshTCPServer[port=10000] started....",则说明设置成功。 + + diff --git a/docs/zh/instruction/03-demo.md b/docs/zh/instruction/03-demo.md new file mode 100644 index 0000000000..5c3f77aee3 --- /dev/null +++ b/docs/zh/instruction/03-demo.md @@ -0,0 +1,178 @@ +# 运行 eventmesh-sdk-java demo + +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.eventmesh/eventmesh-sdk-java/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.apache.eventmesh/eventmesh-sdk-java) + +> EventMesh-sdk-java作为客户端,与eventmesh-runtime通信,用于完成消息的发送和接收。 +> +> EventMesh-sdk-java支持异步消息和广播消息。异步消息表示生产者只发送消息,不关心回复消息。广播消息表示生产者发送一次消息,所有订阅广播主题的消费者都将收到消息 +> +> EventMesh-sdk-java支持HTTP,TCP 和 GRPC 协议。 + +TCP, HTTP 和 GRPC 示例都在**eventmesh-examples**模块下 + +### 1. TCP DEMO + +

异步消息

+ +- 创建主题TEST-TOPIC-TCP-ASYNC,可以通过 rocketmq-console 或者 rocketmq tools 命令 + +- 启动消费者,订阅上一步骤已经创建的Topic + +``` +运行 org.apache.eventmesh.tcp.demo.sub.eventmeshmessage.AsyncSubscribe 的main方法 +``` + +- 启动发送端,发送消息 + +``` +运行 org.apache.eventmesh.tcp.demo.pub.eventmeshmessage.AsyncPublish 的main方法 +``` + +

广播消息

+ +- 创建主题TEST-TOPIC-TCP-BROADCAST,可以通过 rocketmq-console 或者 rocketmq tools 命令 + +- 启动消费端,订阅上一步骤已经创建的Topic + +``` +运行 org.apache.eventmesh.tcp.demo.sub.eventmeshmessage.AsyncSubscribeBroadcast 的main方法 +``` + +- 启动发送端,发送广播消息 + +``` +运行 org.apache.eventmesh.tcp.demo.pub.eventmeshmessage.AsyncPublishBroadcast 的main方法 +``` + +更多关于TCP部分的内容,请参考 [EventMesh TCP](/docs/zh/sdk-java/03-tcp.md) + +### 2. HTTP演示 + +> 对于HTTP,eventmesh-sdk-java对对于异步事件实现了发送与订阅 +> +>在演示中,Java类`LiteMessage`的`content`字段表示一个特殊的协议,因此,如果您要使用eventmesh-sdk-java的http-client,则只需设计协议的内容并在同一时间提供消费者的应用程序。 + +

异步事件

+ +> 生产者将事件发送给下游即可,无需等待响应 + +- 创建主题TEST-TOPIC-HTTP-ASYNC,可以通过rocketmq-console或者rocketmq tools 命令 + +- 启动消费端,订阅Topic + + 异步事件消费端为spring boot demo,运行demo即可启动服务并完成Topic订阅 + +``` +运行 org.apache.eventmesh.http.demo.sub.SpringBootDemoApplication 的main方法 +``` + +- 启动发送端,发送消息 + +``` +运行 org.apache.eventmesh.http.demo.pub.eventmeshmessage.AsyncPublishInstance 的main方法 +``` +更多关于HTTP部分的内容,请参考 [EventMesh HTTP](/docs/zh/sdk-java/02-http.md) + +### 3. GRPC 演示 + +> eventmesh-sdk-java 实现了 gRPC 协议. 它能异步和同步发送事件到 eventmesh-runtime. +> 它可以通过webhook和事件流方式订阅消费事件, 同时也支持 CNCF CloudEvents 协议. + +

异步事件发送 和 webhook订阅

+ +> Async生产者 异步发送事件到 eventmesh-runtime, 不需要等待事件储存到 `event-store` +> 在webhook 消费者, 事件推送到消费者的http endpoint url。这个URL在消费者的 `Subscription` 模型定于. 这方法跟前面的Http eventmsh client类似。 + +- 在rocketmq 创建主题 TEST-TOPIC-GRPC-ASYNC +- 启动 publisher 发送事件 + +``` +运行 org.apache.eventmesh.grpc.pub.eventmeshmessage.AsyncPublishInstance 的main方法 +``` + +- 启动 webhook 消费者 + +``` +运行 org.apache.eventmesh.grpc.sub.app.SpringBootDemoApplication 的main方法 +``` + +

同步事件发送和事件流订阅

+ +> 同步生产者 发送事件到 eventmesh-runtime, 同时等待事件储存到 `event-store` +> 在事件流消费者,事件以流的形式推送到 `ReceiveMsgHook` 客户端。 这方法类似 eventmesh client. + +- 在rocketmq 创建主题 TEST-TOPIC-GRPC-RR +- 启动 Request-Reply publisher 发送事件 + +``` +运行 org.apache.eventmesh.grpc.pub.eventmeshmessage.RequestReplyInstance 的main方法 +``` + +- 启动 stream subscriber + +``` +运行 org.apache.eventmesh.grpc.sub.EventmeshAsyncSubscribe 的main方法 +``` + +

批量事件发布

+ +> 批量发布多个事件到 eventmesh-runtime. 这是异步操作 + +- 在rocketmq 创建主题 TEST-TOPIC-GRPC-ASYNC +- 启动 publisher 来批量发布事件 + +``` +运行 org.apache.eventmesh.grpc.pub.eventmeshmessage.BatchPublishInstance 的main方法 +``` + +更多关于 gRPC 部分的内容,请参考 [EventMesh gRPC](/docs/zh/sdk-java/04-grpc.md) + +### 3.4 测试 + +请参考[EventMesh Store](/docs/zh/instruction/01-store.md) 和 [EventMesh Runtime](/docs/zh/instruction/02-runtime.md) 完成运行环境的部署 + +完成 store 和 runtime 的部署后,就可以在 eventmesh-examples 模块下运行我们的 demo 来体验 eventmesh 了: + + TCP Sub + + ```shell + cd bin + sh tcp_eventmeshmessage_sub.sh + ``` + + TCP Pub + + ```shell + cd bin + sh tcp_pub_eventmeshmessage.sh + ``` + + TCP Sub Broadcast + + ```shell + cd bin + sh tcp_sub_eventmeshmessage_broadcast.sh + ``` + + TCP Pub Broadcast + + ```shell + cd bin + sh tcp_pub_eventmeshmessage_broadcast.sh + ``` + + HTTP Sub + + ```shell + cd bin + sh http_sub.sh + ``` + + HTTP Pub + + ```shell + cd bin + sh http_pub_eventmeshmessage.sh + ``` + + 之后, 你可以在 `/logs` 目录下面看到不同模式的运行日志 diff --git a/docs/zh/instruction/_category_.json b/docs/zh/instruction/_category_.json new file mode 100644 index 0000000000..06fd721fbd --- /dev/null +++ b/docs/zh/instruction/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Instructions", + "collapsed": false +} diff --git a/docs/zh/introduction.md b/docs/zh/introduction.md new file mode 100644 index 0000000000..43c821dd61 --- /dev/null +++ b/docs/zh/introduction.md @@ -0,0 +1,49 @@ +# Apache EventMesh (Incubating) + +[![CI status](https://github.com/apache/incubator-eventmesh/actions/workflows/ci.yml/badge.svg)](https://github.com/apache/incubator-eventmesh/actions/workflows/ci.yml) +[![CodeCov](https://codecov.io/gh/apache/incubator-eventmesh/branch/develop/graph/badge.svg)](https://codecov.io/gh/apache/incubator-eventmesh) +[![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/apache/incubator-eventmesh.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/apache/incubator-eventmesh/context:java) +[![Total alerts](https://img.shields.io/lgtm/alerts/g/apache/incubator-eventmesh.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/apache/incubator-eventmesh/alerts/) +[![GitHub release](https://img.shields.io/badge/release-download-orange.svg)](https://github.com/apache/incubator-eventmesh/releases) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) + +## 什么是Event Mesh? + +EventMesh是一个动态的云原生事件驱动架构基础设施,用于分离应用程序和后端中间件层,它支持广泛的用例,包括复杂的混合云、使用了不同技术栈的分布式架构。 + +![architecture1](../images/eventmesh-define.png) + +**EventMesh架构:** + +![architecture1](../images/eventmesh-runtime.png) + +**EventMesh云原生结构:** + +![architecture2](../images/eventmesh-panels.png) + +Event Mesh允许将来自一个应用程序的事件动态路由到任何其他应用程序. Event Mesh的一般功能: + +* 事件驱动; +* 事件治理; +* 动态路由; +* 云原生 + +部件: + +* eventmesh-runtime:一种中间件,用于在事件生产者和消费者之间传输事件,支持云原生应用程序和微服务 +* eventmesh-sdk-java:当前支持HTTP、HHTTP、TCP和 [gRPC](https://grpc.io) 协议 + + +## 快速开始 + +1. 构建并部署 event-store(RocketMQ), 请参见[说明](instruction/01-store.md) +2. 构建并部署 eventmesh-runtime,请参见[说明](instruction/02-runtime.md) +3. 运行 eventmesh-sdk-java 演示,请参见[说明](instruction/03-demo.md) + +## 贡献 + +永远欢迎参与共建, 请参阅[贡献](../../03-new-contributor-guidelines.md)了解详细指南 + +您可以从发现和解决问题开始~ +[GitHub Issues](https://github.com/apache/incubator-eventmesh/issues) + diff --git a/docs/zh/roadmap.md b/docs/zh/roadmap.md new file mode 100644 index 0000000000..a3d7695cca --- /dev/null +++ b/docs/zh/roadmap.md @@ -0,0 +1,47 @@ +--- +sidebar_position: 1 +--- + +# EventMesh产品路线图 + +下表列出了EventMesh的新特性和bug修复情况,详情请参考 [release notes](https://eventmesh.apache.org/events/release-notes/v1.4.0). + +## List of Features and Milestones + +| Status | Description | Reference | +|-------------------------------------------|---------------------------------| --- | +| **Implemented in 1.0.0** | Support HTTP | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.0.0** | Support TCP | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.0.0** | Support Pub/Sub Event | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.1.1** | Provide Java SDK | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.1.1** | Support HTTPS | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.2.0** | Support RocketMQ as EventStore | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.2.0** | Support Heartbeat | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.3.0** | Integrate with OpenSchema | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.3.0** | Integrate with OpenTelemetry | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.3.0** | Support CloudEvents | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.4.0** | Support gRPC | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.5.0** | Provide Golang SDK | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.5.0** | Support Nacos Registry | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.5.0** | Support Mesh Bridge | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.5.0** | Support Federal Government | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.6.0 (to be released)** | Integrate with Consul | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.6.0 (to be released)** | Support Webhook | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **Implemented in 1.6.0 (to be released)** | Support etcd | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **In Progress** | Knative Eventing Infrastructure | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/790), [GSoC '22](https://issues.apache.org/jira/browse/COMDEV-463) | +| **In Progress** | Dashboard | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/700), [GSoC '22](https://issues.apache.org/jira/browse/COMDEV-465) | +| **In Progress** | Support Kafka as EventStore | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/676) | +| **In Progress** | Support Pulsar as EventStore | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/676) | +| **In Progress** | Support Dledger | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **In Progress** | Workflow | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **In Progress** | Support Redis | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **In Progress** | Support Mesh Bridge | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| **In Progress** | Support Zookeeper | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| Planned | Provide NodeJS SDK | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/417) | +| Planned | Transaction Event | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/697) | +| Planned | Event Query Language (EQL) | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/778) | +| Planned | Metadata consistency persistent | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/817) | +| Planned | Rust SDK | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/815) | +| Planned | WebAssembly Runtime | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/576) | +| Planned | Filter Chain | [GitHub Issue](https://github.com/apache/incubator-eventmesh/issues/664) | + diff --git a/docs/zh/sdk-java/01-intro.md b/docs/zh/sdk-java/01-intro.md new file mode 100644 index 0000000000..cb4b87640c --- /dev/null +++ b/docs/zh/sdk-java/01-intro.md @@ -0,0 +1,29 @@ +# 安装 + +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.eventmesh/eventmesh-sdk-java/badge.svg?style=for-the-badge)](https://maven-badges.herokuapp.com/maven-central/org.apache.eventmesh/eventmesh-sdk-java) + +EventMesh Java SDK 是在一个 Java 应用中集成 Eventmesh 所需的 Java 组件集合。SDK 支持使用 TCP、HTTP 和 gRPC 协议来发送和接收同步消息、异步消息和广播消息。SDK 实现了 EventMesh 消息、CloudEvents 和 OpenMessaging 形式。您可以在 [`eventmesh-example`](https://github.com/apache/incubator-eventmesh/tree/master/eventmesh-examples) 模块中查看示例项目。 + +## Gradle + +使用 Gradle 安装 EventMesh Java SDK,您需要在模块的 `build.gradle` 文件的依赖块中将 `org.apache.eventmesh:eventmesh-sdk-java` 声明为 `implementation`。 + +```groovy +dependencies { + implementation 'org.apache.eventmesh:eventmesh-sdk-java:1.4.0' +} +``` + +## Maven + +使用 Maven 安装 EventMesh Java SDK,您需要在项目 `pom.xml` 文件的依赖块中声明 `org.apache.eventmesh:eventmesh-sdk-java`。 + +```xml + + + org.apache.eventmesh + eventmesh-sdk-java + 1.4.0 + + +``` \ No newline at end of file diff --git a/docs/zh/sdk-java/02-http.md b/docs/zh/sdk-java/02-http.md new file mode 100644 index 0000000000..9a8acd0d68 --- /dev/null +++ b/docs/zh/sdk-java/02-http.md @@ -0,0 +1,118 @@ +# HTTP 协议 + +EventMesh Java SDK 实现了 HTTP 异步消息的生产者和消费者。二者都需要一个 `EventMeshHttpClientConfig` 类实例来指定 EventMesh HTTP 客户端的配置信息。其中的 `liteEventMeshAddr`、`userName` 和 `password` 字段需要和 EventMesh runtime `eventmesh.properties` 文件中的相匹配。 + +```java +import org.apache.eventmesh.client.http.conf.EventMeshHttpClientConfig; +import org.apache.eventmesh.common.utils.IPUtils; +import org.apache.eventmesh.common.utils.ThreadUtils; + +public class HTTP { + public static void main(String[] args) throws Exception { + EventMeshHttpClientConfig eventMeshClientConfig = EventMeshHttpClientConfig.builder() + .liteEventMeshAddr("localhost:10105") + .producerGroup("TEST_PRODUCER_GROUP") + .env("env") + .idc("idc") + .ip(IPUtils.getLocalAddress()) + .sys("1234") + .pid(String.valueOf(ThreadUtils.getPID())) + .userName("eventmesh") + .password("password") + .build(); + /* ... */ + } +} +``` + +## HTTP 消费者 + +类 `EventMeshHttpConsumer` 实现了 `heartbeat`、`subscribe` 和 `unsubscribe` 方法。`subscribe` 方法接收一个 `SubscriptionItem` 对象的列表,其中定义了要订阅的话题和回调的 URL 地址。 + +```java +import org.apache.eventmesh.client.http.consumer.EventMeshHttpConsumer; +import org.apache.eventmesh.common.protocol.SubscriptionItem; +import org.apache.eventmesh.common.protocol.SubscriptionMode; +import org.apache.eventmesh.common.protocol.SubscriptionType; +import com.google.common.collect.Lists; + +public class HTTP { + final String url = "http://localhost:8080/callback"; + final List topicList = Lists.newArrayList( + new SubscriptionItem("eventmesh-async-topic", SubscriptionMode.CLUSTERING, SubscriptionType.ASYNC) + ); + + public static void main(String[] args) throws Exception { + /* ... */ + eventMeshHttpConsumer = new EventMeshHttpConsumer(eventMeshClientConfig); + eventMeshHttpConsumer.heartBeat(topicList, url); + eventMeshHttpConsumer.subscribe(topicList, url); + /* ... */ + eventMeshHttpConsumer.unsubscribe(topicList, url); + } +} +``` + +EventMesh runtime 将发送一个包含 [CloudEvents 格式](https://github.com/cloudevents/spec) 信息的 POST 请求到这个回调的 URL 地址。类 [SubController.java](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-examples/src/main/java/org/apache/eventmesh/http/demo/sub/controller/SubController.java) 实现了 Spring Boot controller,它将接收并解析回调信息。 + +## HTTP 生产者 + +类 `EventMeshHttpProducer` 实现了 `publish` 方法。`publish` 方法接收将被发布的消息和一个可选的 timeout 值。消息应是下列类的一个实例: + +- `org.apache.eventmesh.common.EventMeshMessage` +- `io.cloudevents.CloudEvent` +- `io.openmessaging.api.Message` + +```java +import org.apache.eventmesh.client.http.producer.EventMeshHttpProducer; +import org.apache.eventmesh.client.tcp.common.EventMeshCommon; +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.utils.JsonUtils; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; + +public class HTTP { + public static void main(String[] args) throws Exception { + /* ... */ + EventMeshHttpProducer eventMeshHttpProducer = new EventMeshHttpProducer(eventMeshClientConfig); + Map content = new HashMap<>(); + content.put("content", "testAsyncMessage"); + + CloudEvent event = CloudEventBuilder.v1() + .withId(UUID.randomUUID().toString()) + .withSubject("eventmesh-async-topic") + .withSource(URI.create("/")) + .withDataContentType("application/cloudevents+json") + .withType(EventMeshCommon.CLOUD_EVENTS_PROTOCOL_NAME) + .withData(JsonUtils.serialize(content).getBytes(StandardCharsets.UTF_8)) + .withExtension(Constants.EVENTMESH_MESSAGE_CONST_TTL, String.valueOf(4 * 1000)) + .build(); + eventMeshHttpProducer.publish(event); + } +} +``` + +## 使用Curl 命令 + +本段落介绍通过Curl命令体验事件的收发功能 + +### 事件发送 + +启动EventMesh Runtime服务后,可以使用Curl命令将事件用HTTP POST方法发布到指定的主题,Body内容必须是JSON格式,执行命令示例如下: + +```shell +curl -H "Content-Type:application/json" -X POST -d '{"name": "admin", "pass":"12345678"}' http://127.0.0.1:10105/eventmesh/publish/TEST-TOPIC-HTTP-ASYNC +``` + + + +### 事件订阅 + +启动EventMesh Runtime服务后,可以使用Curl命令用HTTP POST方法订阅指定的主题列表,Body内容必须是JSON格式,执行命令示例如下: + +```shell +curl -H "Content-Type:application/json" -X POST -d '{"url": "http://127.0.0.1:8088/sub/test", "consumerGroup":"TEST-GROUP", "topic":[{"mode":"CLUSTERING","topic":"TEST-TOPIC-HTTP-ASYNC","type":"ASYNC"}]}' http://127.0.0.1:10105/eventmesh/subscribe/local +``` + +你可以在项目`eventmesh-examples`模块中看到这个例子。 \ No newline at end of file diff --git a/docs/zh/sdk-java/03-tcp.md b/docs/zh/sdk-java/03-tcp.md new file mode 100644 index 0000000000..54f5eca556 --- /dev/null +++ b/docs/zh/sdk-java/03-tcp.md @@ -0,0 +1,118 @@ +# TCP 协议 + +EventMesh Java SDK 实现了同步、异步和广播 TCP 消息的生产者和消费者。 二者都需要一个 `EventMeshHttpClientConfig` 类实例来指定 EventMesh TCP 客户端的配置信息。其中的 `host` 和 `port` 字段需要和 EventMesh runtime `eventmesh.properties` 文件中的相匹配。 + +```java +import org.apache.eventmesh.client.tcp.conf.EventMeshTCPClientConfig; +import org.apache.eventmesh.client.tcp.common.ReceiveMsgHook; +import io.cloudevents.CloudEvent; + +public class AsyncSubscribe implements ReceiveMsgHook { + public static void main(String[] args) throws InterruptedException { + EventMeshTCPClientConfig eventMeshTcpClientConfig = EventMeshTCPClientConfig.builder() + .host(eventMeshIp) + .port(eventMeshTcpPort) + .userAgent(userAgent) + .build(); + /* ... */ + } +} +``` + +## TCP 消费者 + +消费者应该实现 `ReceiveMsgHook` 类,其被定义在 [ReceiveMsgHook.java](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-sdk-java/src/main/java/org/apache/eventmesh/client/tcp/common/ReceiveMsgHook.java)。 + +```java +public interface ReceiveMsgHook { + Optional handle(ProtocolMessage msg); +} +``` + +类 `EventMeshTCPClient` 实现了 `subscribe` 方法。该方法接收话题、`SubscriptionMode` 和 `SubscriptionType`。`handle` 方法将会在消费者从订阅的话题中收到消息时被调用。如果 `SubscriptionType` 是 `SYNC`,`handle` 的返回值将被发送回生产者。 + +```java +import org.apache.eventmesh.client.tcp.EventMeshTCPClient; +import org.apache.eventmesh.client.tcp.EventMeshTCPClientFactory; +import org.apache.eventmesh.client.tcp.common.ReceiveMsgHook; +import org.apache.eventmesh.common.protocol.SubscriptionMode; +import org.apache.eventmesh.common.protocol.SubscriptionType; +import io.cloudevents.CloudEvent; + +public class TCPConsumer implements ReceiveMsgHook { + public static TCPConsumer handler = new TCPConsumer(); + private static EventMeshTCPClient client; + + public static void main(String[] args) throws Exception { + client = EventMeshTCPClientFactory.createEventMeshTCPClient( + eventMeshTcpClientConfig, + CloudEvent.class + ); + client.init(); + + client.subscribe( + "eventmesh-sync-topic", + SubscriptionMode.CLUSTERING, + SubscriptionType.SYNC + ); + + client.registerSubBusiHandler(handler); + client.listen(); + } + + @Override + public Optional handle(CloudEvent message) { + log.info("Messaged received: {}", message); + return Optional.of(message); + } +} +``` + +## TCP 生产者 + +### 异步生产者 + +类 `EventMeshTCPClient` 实现了 `public` 方法。该方法接收将被发布的消息和一个可选的 timeout 值,并返回来自消费者的响应消息。 + +```java +/* ... */ +client = EventMeshTCPClientFactory.createEventMeshTCPClient(eventMeshTcpClientConfig, CloudEvent.class); +client.init(); + +CloudEvent event = CloudEventBuilder.v1() + .withId(UUID.randomUUID().toString()) + .withSubject(ExampleConstants.EVENTMESH_GRPC_ASYNC_TEST_TOPIC) + .withSource(URI.create("/")) + .withDataContentType(ExampleConstants.CLOUDEVENT_CONTENT_TYPE) + .withType(EventMeshCommon.CLOUD_EVENTS_PROTOCOL_NAME) + .withData(JsonUtils.serialize(content).getBytes(StandardCharsets.UTF_8)) + .withExtension(Constants.EVENTMESH_MESSAGE_CONST_TTL, String.valueOf(4 * 1000)) + .build(); +client.publish(event, 1000); +``` + +### 同步生产者 + +类 `EventMeshTCPClient` 实现了 `rr` 方法。该方法接收将被发布的消息和一个可选的 timeout 值,并返回来自消费者的响应消息。 + +```java +/* ... */ +client = EventMeshTCPClientFactory.createEventMeshTCPClient(eventMeshTcpClientConfig, CloudEvent.class); +client.init(); + +CloudEvent event = CloudEventBuilder.v1() + .withId(UUID.randomUUID().toString()) + .withSubject(ExampleConstants.EVENTMESH_GRPC_ASYNC_TEST_TOPIC) + .withSource(URI.create("/")) + .withDataContentType(ExampleConstants.CLOUDEVENT_CONTENT_TYPE) + .withType(EventMeshCommon.CLOUD_EVENTS_PROTOCOL_NAME) + .withData(JsonUtils.serialize(content).getBytes(StandardCharsets.UTF_8)) + .withExtension(Constants.EVENTMESH_MESSAGE_CONST_TTL, String.valueOf(4 * 1000)) + .build(); + +Package response = client.rr(event, 1000); +CloudEvent replyEvent = EventFormatProvider + .getInstance() + .resolveFormat(JsonFormat.CONTENT_TYPE) + .deserialize(response.getBody().toString().getBytes(StandardCharsets.UTF_8)); +``` \ No newline at end of file diff --git a/docs/zh/sdk-java/04-grpc.md b/docs/zh/sdk-java/04-grpc.md new file mode 100644 index 0000000000..b078187071 --- /dev/null +++ b/docs/zh/sdk-java/04-grpc.md @@ -0,0 +1,174 @@ +# gRPC 协议 + +EventMesh Java SDK 实现了 gRPC 同步、异步和广播消息的生产者和消费者。二者都需要一个 `EventMeshHttpClientConfig` 类实例来指定 EventMesh gRPC 客户端的配置信息。其中的 `liteEventMeshAddr`、`userName` 和 `password` 字段需要和 EventMesh runtime `eventmesh.properties` 文件中的相匹配。 + +```java +import org.apache.eventmesh.client.grpc.config.EventMeshGrpcClientConfig; +import org.apache.eventmesh.client.grpc.consumer.ReceiveMsgHook; +import io.cloudevents.CloudEvent; + +public class CloudEventsAsyncSubscribe implements ReceiveMsgHook { + public static void main(String[] args) throws InterruptedException { + EventMeshGrpcClientConfig eventMeshClientConfig = EventMeshGrpcClientConfig.builder() + .serverAddr("localhost") + .serverPort(10205) + .consumerGroup(ExampleConstants.DEFAULT_EVENTMESH_TEST_CONSUMER_GROUP) + .env("env").idc("idc") + .sys("1234").build(); + /* ... */ + } +} +``` + +## gRPC 消费者 + +### 流消费者 + +EventMesh runtime 会将来自生产者的信息作为一系列事件流向流消费者发送。消费者应实现 `ReceiveHook` 类,其被定义在 [ReceiveMsgHook.java](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-sdk-java/src/main/java/org/apache/eventmesh/client/grpc/consumer/ReceiveMsgHook.java)。 + +```java +public interface ReceiveMsgHook { + Optional handle(T msg) throws Throwable; + String getProtocolType(); +} +``` + +类 `EventMeshGrpcConsumer` 实现了 `registerListener`、`subscribe` 和 `unsubscribe` 方法。`subscribe` 方法接收一个 `SubscriptionItem` 对象的列表,其中定义了要订阅的话题。`registerListener` 接收一个实现了 `ReceiveMsgHook` 的实例。`handle` 方法将会在消费者收到订阅的主题消息时被调用。如果 `SubscriptionType` 是 `SYNC`,`handle` 的返回值将被发送回生产者。 + +```java +import org.apache.eventmesh.client.grpc.consumer.EventMeshGrpcConsumer; +import org.apache.eventmesh.client.grpc.consumer.ReceiveMsgHook; +import org.apache.eventmesh.client.tcp.common.EventMeshCommon; +import org.apache.eventmesh.common.protocol.SubscriptionItem; +import org.apache.eventmesh.common.protocol.SubscriptionMode; +import org.apache.eventmesh.common.protocol.SubscriptionType; +import io.cloudevents.CloudEvent; + +public class CloudEventsAsyncSubscribe implements ReceiveMsgHook { + public static CloudEventsAsyncSubscribe handler = new CloudEventsAsyncSubscribe(); + public static void main(String[] args) throws InterruptedException { + /* ... */ + SubscriptionItem subscriptionItem = new SubscriptionItem( + "eventmesh-async-topic", + SubscriptionMode.CLUSTERING, + SubscriptionType.ASYNC + ); + EventMeshGrpcConsumer eventMeshGrpcConsumer = new EventMeshGrpcConsumer(eventMeshClientConfig); + + eventMeshGrpcConsumer.init(); + eventMeshGrpcConsumer.registerListener(handler); + eventMeshGrpcConsumer.subscribe(Collections.singletonList(subscriptionItem)); + /* ... */ + eventMeshGrpcConsumer.unsubscribe(Collections.singletonList(subscriptionItem)); + } + + @Override + public Optional handle(CloudEvent message) { + log.info("Messaged received: {}", message); + return Optional.empty(); + } + + @Override + public String getProtocolType() { + return EventMeshCommon.CLOUD_EVENTS_PROTOCOL_NAME; + } +} +``` + +### Webhook 消费者 + +类 `EventMeshGrpcConsumer` 的 `subscribe` 方法接收一个 `SubscriptionItem` 对象的列表,其中定义了要订阅的主题和一个可选的 timeout 值。如果提供了回调 URL,EventMesh runtime 将向回调 URL 地址发送一个包含 [CloudEvents 格式](https://github.com/cloudevents/spec) 消息的 POST 请求。[SubController.java](https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-examples/src/main/java/org/apache/eventmesh/grpc/sub/app/controller/SubController.java) 实现了一个接收并解析回调信息的 Spring Boot controller。 + +```java +import org.apache.eventmesh.client.grpc.consumer.EventMeshGrpcConsumer; +import org.apache.eventmesh.client.grpc.consumer.ReceiveMsgHook; +import org.apache.eventmesh.client.tcp.common.EventMeshCommon; +import org.apache.eventmesh.common.protocol.SubscriptionItem; +import org.apache.eventmesh.common.protocol.SubscriptionMode; +import org.apache.eventmesh.common.protocol.SubscriptionType; + +@Component +public class SubService implements InitializingBean { + final String url = "http://localhost:8080/callback"; + + public void afterPropertiesSet() throws Exception { + /* ... */ + eventMeshGrpcConsumer = new EventMeshGrpcConsumer(eventMeshClientConfig); + eventMeshGrpcConsumer.init(); + + SubscriptionItem subscriptionItem = new SubscriptionItem( + "eventmesh-async-topic", + SubscriptionMode.CLUSTERING, + SubscriptionType.ASYNC + ); + + eventMeshGrpcConsumer.subscribe(Collections.singletonList(subscriptionItem), url); + /* ... */ + eventMeshGrpcConsumer.unsubscribe(Collections.singletonList(subscriptionItem), url); + } +} +``` + +## gRPC 生产者 + +### 异步生产者 + +类 `EventMeshGrpcProducer` 实现了 `publish` 方法。`publish` 方法接收将被发布的消息和一个可选的 timeout 值。消息应是下列类的一个实例: + +- `org.apache.eventmesh.common.EventMeshMessage` +- `io.cloudevents.CloudEvent` + +```java +/* ... */ +EventMeshGrpcProducer eventMeshGrpcProducer = new EventMeshGrpcProducer(eventMeshClientConfig); +eventMeshGrpcProducer.init(); + +Map content = new HashMap<>(); +content.put("content", "testAsyncMessage"); + +CloudEvent event = CloudEventBuilder.v1() + .withId(UUID.randomUUID().toString()) + .withSubject(ExampleConstants.EVENTMESH_GRPC_ASYNC_TEST_TOPIC) + .withSource(URI.create("/")) + .withDataContentType(ExampleConstants.CLOUDEVENT_CONTENT_TYPE) + .withType(EventMeshCommon.CLOUD_EVENTS_PROTOCOL_NAME) + .withData(JsonUtils.serialize(content).getBytes(StandardCharsets.UTF_8)) + .withExtension(Constants.EVENTMESH_MESSAGE_CONST_TTL, String.valueOf(4 * 1000)) + .build(); +eventMeshGrpcProducer.publish(event); +``` + +### 同步生产者 + +类 `EventMeshGrpcProducer` 实现了 `requestReply` 方法。`requestReply` 方法接收将被发布的消息和一个可选的 timeout 值。方法会返回消费者返回的消息。消息应是下列类的一个实例: + +- `org.apache.eventmesh.common.EventMeshMessage` +- `io.cloudevents.CloudEvent` + +### 批量生产者 + +类 `EventMeshGrpcProducer` 重写了 `publish` 方法,该方法接收一个将被发布的消息列表和一个可选的 timeout 值。列表中的消息应是下列类的一个实例: + +- `org.apache.eventmesh.common.EventMeshMessage` +- `io.cloudevents.CloudEvent` + +```java +/* ... */ +List cloudEventList = new ArrayList<>(); +for (int i = 0; i < 5; i++) { + CloudEvent event = CloudEventBuilder.v1() + .withId(UUID.randomUUID().toString()) + .withSubject(ExampleConstants.EVENTMESH_GRPC_ASYNC_TEST_TOPIC) + .withSource(URI.create("/")) + .withDataContentType(ExampleConstants.CLOUDEVENT_CONTENT_TYPE) + .withType(EventMeshCommon.CLOUD_EVENTS_PROTOCOL_NAME) + .withData(JsonUtils.serialize(content).getBytes(StandardCharsets.UTF_8)) + .withExtension(Constants.EVENTMESH_MESSAGE_CONST_TTL, String.valueOf(4 * 1000)) + .build(); + + cloudEventList.add(event); +} + +eventMeshGrpcProducer.publish(cloudEventList); +/* ... */ +``` \ No newline at end of file diff --git a/docs/zh/sdk-java/_category_.json b/docs/zh/sdk-java/_category_.json new file mode 100644 index 0000000000..9d0a27c562 --- /dev/null +++ b/docs/zh/sdk-java/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "EventMesh SDK for Java", + "collapsed": false +} diff --git a/eventmesh-acl/build.gradle b/eventmesh-acl/build.gradle deleted file mode 100644 index 11bbc47bf2..0000000000 --- a/eventmesh-acl/build.gradle +++ /dev/null @@ -1,14 +0,0 @@ -plugins { - id 'java' -} - -group 'cn.webank.defibus' -version '1.0.0' - -repositories { - mavenCentral() -} - -dependencies { - testCompile group: 'junit', name: 'junit', version: '4.12' -} diff --git a/eventmesh-admin/README.md b/eventmesh-admin/README.md new file mode 100644 index 0000000000..69db9bb59a --- /dev/null +++ b/eventmesh-admin/README.md @@ -0,0 +1,53 @@ +# EventMesh Administration Module + +EventMesh Administration Module for EventMesh. It manages Admin Service, Configurations such as topics/subscriptions management.It works as a control plane and provide some interface to manage the eventmesh-runtime module and other configurations. + +## Administration Client Manager APIs + +### POST /topicManage +- Create a new topic if does not exist +- Exposed POST endpoint to create a new topic if it does not exist. + * Url - http://localhost:8081/topicManage + * sample request payload + ```json + { + "name": "mytopic1" + } + ``` + + Sample response + + ```json + { + "topic": "mytopic1", + "created_time": "2021-09-03", + } + ``` +### DELETE /topicManage/(string: topic) +- Delete a specific topic. +- Exposed DELETE endpoint to remove a specific topic + * URL - + ```url + http://localhost:8081/topicManage/mytopic1 + ``` + + * Response - + + ```json + { + "topic": "mytopic1", + } + ``` + +### GET /topicManage +- Retrieve a list of topics +- Exposed GET endpoint to retrieve all topics + * URL - + ```url + http://localhost:8081/topicManage + ``` + * Response + + ```json + ["mytopic1", "mytopic2"] + ``` diff --git a/eventmesh-admin/build.gradle b/eventmesh-admin/build.gradle new file mode 100644 index 0000000000..2944f98194 --- /dev/null +++ b/eventmesh-admin/build.gradle @@ -0,0 +1,16 @@ +/* + * 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. + */ diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/build.gradle b/eventmesh-admin/eventmesh-admin-rocketmq/build.gradle new file mode 100644 index 0000000000..1217b33818 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/build.gradle @@ -0,0 +1,30 @@ +/* + * 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. + */ + + +dependencies { + compileOnly project(":eventmesh-common") + + implementation "org.apache.httpcomponents:httpclient" + implementation "com.fasterxml.jackson.core:jackson-databind" + implementation "com.fasterxml.jackson.core:jackson-core" + implementation "com.fasterxml.jackson.core:jackson-annotations" + + implementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + + testImplementation project(":eventmesh-connector-plugin:eventmesh-connector-api") +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/gradle.properties b/eventmesh-admin/eventmesh-admin-rocketmq/gradle.properties new file mode 100644 index 0000000000..7c28639929 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/gradle.properties @@ -0,0 +1,17 @@ +# 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. +# + +rocketmq_version=4.9.3 \ No newline at end of file diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/Constants.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/Constants.java new file mode 100644 index 0000000000..9a61dee92d --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/Constants.java @@ -0,0 +1,29 @@ +/* + * 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. + */ + +package org.apache.eventmesh.admin.rocketmq; + +public class Constants { + + public static final String TOPIC_MANAGE_PATH = "/topicManage"; + + public static final String CONTENT_TYPE = "Content-Type"; + + public static final String APPLICATION_JSON = "application/json"; + + public static final String TOPIC_ERROR = "create topic failed! Server side error"; +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/controller/AdminController.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/controller/AdminController.java new file mode 100644 index 0000000000..9b85b4521c --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/controller/AdminController.java @@ -0,0 +1,44 @@ +/* + * 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. + */ + +package org.apache.eventmesh.admin.rocketmq.controller; + +import static org.apache.eventmesh.admin.rocketmq.Constants.TOPIC_MANAGE_PATH; + +import org.apache.eventmesh.admin.rocketmq.handler.TopicsHandler; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.net.httpserver.HttpServer; + +public class AdminController { + + private static final Logger logger = LoggerFactory.getLogger(AdminController.class); + + public AdminController() { + } + + public void run(HttpServer server) throws IOException { + + server.createContext(TOPIC_MANAGE_PATH, new TopicsHandler()); + + logger.info("EventMesh-Admin Controller server context created successfully"); + } +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/handler/TopicsHandler.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/handler/TopicsHandler.java new file mode 100644 index 0000000000..0c0dffd7c1 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/handler/TopicsHandler.java @@ -0,0 +1,100 @@ +/* + * 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. + */ + +package org.apache.eventmesh.admin.rocketmq.handler; + +import static org.apache.eventmesh.admin.rocketmq.Constants.APPLICATION_JSON; +import static org.apache.eventmesh.admin.rocketmq.Constants.CONTENT_TYPE; +import static org.apache.eventmesh.admin.rocketmq.Constants.TOPIC_ERROR; +import static org.apache.eventmesh.admin.rocketmq.Constants.TOPIC_MANAGE_PATH; + +import org.apache.eventmesh.admin.rocketmq.request.TopicCreateRequest; +import org.apache.eventmesh.admin.rocketmq.response.TopicResponse; +import org.apache.eventmesh.admin.rocketmq.util.RequestMapping; +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.utils.JsonUtils; +import org.apache.eventmesh.common.utils.NetUtils; + +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.io.OutputStream; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + +public class TopicsHandler implements HttpHandler { + private static final Logger logger = LoggerFactory.getLogger(TopicsHandler.class); + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + + // create a new topic + if (RequestMapping.postMapping(TOPIC_MANAGE_PATH, httpExchange)) { + createTopicHandler(httpExchange); + return; + } + + OutputStream out = httpExchange.getResponseBody(); + httpExchange.sendResponseHeaders(500, 0); + String result = String.format("Please check your request url: %s", httpExchange.getRequestURI()); + logger.error(result); + out.write(result.getBytes(Constants.DEFAULT_CHARSET)); + } + + public void createTopicHandler(HttpExchange httpExchange) throws IOException { + String result; + try (OutputStream out = httpExchange.getResponseBody()) { + String params = NetUtils.parsePostBody(httpExchange); + TopicCreateRequest topicCreateRequest = + JsonUtils.deserialize(params, TopicCreateRequest.class); + String topic = topicCreateRequest.getName(); + + if (StringUtils.isBlank(topic)) { + result = "Create topic failed. Parameter topic not found."; + logger.error(result); + out.write(result.getBytes(Constants.DEFAULT_CHARSET)); + return; + } + + //TBD: A new rocketmq service will be implemented for creating topics + TopicResponse topicResponse = null; + if (topicResponse != null) { + logger.info("create a new topic: {}", topic); + httpExchange.getResponseHeaders().add(CONTENT_TYPE, APPLICATION_JSON); + NetUtils.sendSuccessResponseHeaders(httpExchange); + result = JsonUtils.serialize(topicResponse); + logger.info(result); + out.write(result.getBytes(Constants.DEFAULT_CHARSET)); + } else { + httpExchange.sendResponseHeaders(500, 0); + result = TOPIC_ERROR; + logger.error(result); + out.write(result.getBytes(Constants.DEFAULT_CHARSET)); + } + } catch (Exception e) { + httpExchange.getResponseHeaders().add(CONTENT_TYPE, APPLICATION_JSON); + httpExchange.sendResponseHeaders(500, 0); + result = TOPIC_ERROR; + logger.error(result, e); + } + } + +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/request/TopicCreateRequest.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/request/TopicCreateRequest.java new file mode 100644 index 0000000000..7adaa77cd2 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/request/TopicCreateRequest.java @@ -0,0 +1,47 @@ +/* + * 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. + */ + +package org.apache.eventmesh.admin.rocketmq.request; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public class TopicCreateRequest { + + private String name; + + @JsonCreator + public TopicCreateRequest(@JsonProperty("name") String topic) { + super(); + this.name = topic; + } + + @JsonProperty("name") + public String getName() { + return this.name; + } + + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/response/TopicResponse.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/response/TopicResponse.java new file mode 100644 index 0000000000..41b6e6a9b2 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/response/TopicResponse.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +package org.apache.eventmesh.admin.rocketmq.response; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class TopicResponse { + + private String topic; + private String createdTime; + + @JsonCreator + public TopicResponse(@JsonProperty("topic") String topic, + @JsonProperty("created_time") String createdTime) { + super(); + this.topic = topic; + this.createdTime = createdTime; + } + + @JsonProperty("topic") + public String getTopic() { + return this.topic; + } + + @JsonProperty("topic") + public void setTopic(String topic) { + this.topic = topic; + } + + @JsonProperty("created_time") + public String getCreatedTime() { + return createdTime; + } + + @JsonProperty("created_time") + public void setCreatedTime(String createdTime) { + this.createdTime = createdTime; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("TopicResponse {topic=" + this.topic + ","); + sb.append("created_time=" + this.createdTime + "}"); + return sb.toString(); + } + +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/RequestMapping.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/RequestMapping.java new file mode 100644 index 0000000000..e796e49edc --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/RequestMapping.java @@ -0,0 +1,62 @@ +/* + * 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. + */ + +package org.apache.eventmesh.admin.rocketmq.util; + +import org.apache.eventmesh.common.enums.HttpMethod; + +import com.sun.net.httpserver.HttpExchange; + +public class RequestMapping { + + public static boolean postMapping(String value, HttpExchange httpExchange) { + if (HttpMethod.POST.name().equalsIgnoreCase(httpExchange.getRequestMethod())) { + String requestUri = httpExchange.getRequestURI().getPath(); + UrlMappingPattern matcher = new UrlMappingPattern(value); + return matcher.matches(requestUri); + } + return false; + } + + public static boolean getMapping(String value, HttpExchange httpExchange) { + if (HttpMethod.GET.name().equalsIgnoreCase(httpExchange.getRequestMethod())) { + String requestUri = httpExchange.getRequestURI().getPath(); + UrlMappingPattern matcher = new UrlMappingPattern(value); + return matcher.matches(requestUri); + } + return false; + } + + public static boolean putMapping(String value, HttpExchange httpExchange) { + if (HttpMethod.PUT.name().equalsIgnoreCase(httpExchange.getRequestMethod())) { + String requestUri = httpExchange.getRequestURI().getPath(); + UrlMappingPattern matcher = new UrlMappingPattern(value); + return matcher.matches(requestUri); + } + return false; + } + + public static boolean deleteMapping(String value, HttpExchange httpExchange) { + if (HttpMethod.DELETE.name().equalsIgnoreCase(httpExchange.getRequestMethod())) { + String requestUri = httpExchange.getRequestURI().getPath(); + UrlMappingPattern matcher = new UrlMappingPattern(value); + return matcher.matches(requestUri); + } + return false; + } + +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/UrlMappingPattern.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/UrlMappingPattern.java new file mode 100644 index 0000000000..09d0eb3d67 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/UrlMappingPattern.java @@ -0,0 +1,109 @@ +/* + * 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. + */ + +package org.apache.eventmesh.admin.rocketmq.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class UrlMappingPattern { + + private static final String URL_PARAMETER_REGEX = "\\{(\\w*?)\\}"; + + private static final String URL_PARAMETER_MATCH_REGEX = + "\\([%\\\\w-.\\\\~!\\$&'\\\\(\\\\)\\\\*\\\\+,;=:\\\\[\\\\]@]+?\\)"; + + private static final Pattern URL_PARAMETER_PATTERN = Pattern.compile(URL_PARAMETER_REGEX); + + private static final String URL_FORMAT_REGEX = "(?:\\.\\{format\\})$"; + + private static final String URL_FORMAT_MATCH_REGEX = "(?:\\\\.\\([\\\\w%]+?\\))?"; + + private static final String URL_QUERY_STRING_REGEX = "(?:\\?.*?)?$"; + + private String urlMappingPattern; + + private Pattern compiledUrlMappingPattern; + + private List paramNames = new ArrayList(); + + public UrlMappingPattern(String pattern) { + super(); + setUrlMappingPattern(pattern); + compile(); + } + + public String getMappingPattern() { + return getUrlMappingPattern().replaceFirst(URL_FORMAT_REGEX, ""); + } + + private String getUrlMappingPattern() { + return urlMappingPattern; + } + + public Map extractPathParameterValues(String url) { + Matcher matcher = compiledUrlMappingPattern.matcher(url); + if (matcher.matches()) { + return extractParameters(matcher); + } + return null; + } + + public boolean matches(String url) { + return (extractPathParameterValues(url) != null); + } + + public void compile() { + acquireParamNames(); + String parsedPattern = + getUrlMappingPattern().replaceFirst(URL_FORMAT_REGEX, URL_FORMAT_MATCH_REGEX); + parsedPattern = parsedPattern.replaceAll(URL_PARAMETER_REGEX, URL_PARAMETER_MATCH_REGEX); + this.compiledUrlMappingPattern = Pattern.compile(parsedPattern + URL_QUERY_STRING_REGEX); + } + + private void acquireParamNames() { + Matcher m = URL_PARAMETER_PATTERN.matcher(getUrlMappingPattern()); + while (m.find()) { + paramNames.add(m.group(1)); + } + } + + private Map extractParameters(Matcher matcher) { + Map values = new HashMap(); + for (int i = 0; i < matcher.groupCount(); i++) { + String value = matcher.group(i + 1); + + if (value != null) { + values.put(paramNames.get(i), value); + } + } + return values; + } + + private void setUrlMappingPattern(String pattern) { + this.urlMappingPattern = pattern; + } + + public List getParamNames() { + return Collections.unmodifiableList(paramNames); + } +} diff --git a/eventmesh-admin/gradle.properties b/eventmesh-admin/gradle.properties new file mode 100644 index 0000000000..a9fd83fea0 --- /dev/null +++ b/eventmesh-admin/gradle.properties @@ -0,0 +1,16 @@ +# +# 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. +# \ No newline at end of file diff --git a/eventmesh-catalog-go/.golangci.yml b/eventmesh-catalog-go/.golangci.yml new file mode 100644 index 0000000000..b2571fc040 --- /dev/null +++ b/eventmesh-catalog-go/.golangci.yml @@ -0,0 +1,99 @@ +# +# 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. + +linters-settings: + funlen: + lines: 80 + statements: 80 + goconst: + min-len: 2 + min-occurrences: 3 + gocyclo: + min-complexity: 20 + golint: + min-confidence: 0 + govet: + check-shadowing: true + lll: + line-length: 120 + errcheck: + check-type-assertions: false + gocritic: + enabled-checks: + - nestingReduce + settings: + nestingReduce: + bodyWidth: 5 + +linters: + disable-all: true + enable: + - deadcode + - funlen + - goconst + - gocyclo + - gofmt + - ineffassign + - staticcheck + - structcheck + - goimports + - revive + - gosimple + - govet + - typecheck + - lll + - rowserrcheck + - errcheck + - unused + - varcheck + - sqlclosecheck + +run: + timeout: 20m + +issues: + exclude-use-default: true + + # The list of ids of default excludes to include or disable. By default it's empty. + include: + - EXC0004 # govet (possible misuse of unsafe.Pointer|should have signature) + - EXC0005 # staticcheck ineffective break statement. Did you mean to break out of the outer loop + - EXC0011 # stylecheck (comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form) + - EXC0012 # revive exported (method|function|type|const) (.+) should have comment or be unexported + + exclude-rules: + - path: _test\.go + linters: + - funlen + - linters: + - staticcheck + text: "SA6002: argument should be pointer-like to avoid allocations" # sync.pool.Put(buf), slice `var buf []byte` will tiger this + - linters: + - structcheck + text: "Store` is unused" + - linters: + - lll + source: "^//go:generate " + + max-same-issues: 0 + new: false + max-issues-per-linter: 0 + +output: + sort-results: true + +service: + golangci-lint-version: 1.23.x diff --git a/eventmesh-catalog-go/Makefile b/eventmesh-catalog-go/Makefile new file mode 100644 index 0000000000..a51b0b1832 --- /dev/null +++ b/eventmesh-catalog-go/Makefile @@ -0,0 +1,40 @@ +# +# 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. + +lint: + golangci-lint run --tests=false +build: + CGO_ENABLED=0 go build -o bin/eventmesh-catalog +# goimports +# -e report all errors (not just the first 10 on different lines) +# -d display diffs instead of rewriting files +# -local put imports beginning with this string after 3rd-party packages; comma-separated list +# gofmt +# -e report all errors (not just the first 10 on different lines) +# -d display diffs instead of rewriting files +# -s simplify code +# -w write result to (source) file instead of stdout +fmt: + find . -name "*.go" | xargs goimports -e -d -local git.code.oa.com -w && \ + find . -name "*.go" | xargs gofmt -e -d -s -w +test: + go test -v ./... -gcflags "all=-N -l" + +cover: + go test ./... -gcflags "all=-N -l" --covermode=count -coverprofile=cover.out.tmp + cat cover.out.tmp | grep -v "_mock.go" | grep -v ".pb.go" > cover.out + rm cover.out.tmp + go tool cover -html=cover.out \ No newline at end of file diff --git a/eventmesh-catalog-go/api/catalog.go b/eventmesh-catalog-go/api/catalog.go new file mode 100644 index 0000000000..8f4a8fb502 --- /dev/null +++ b/eventmesh-catalog-go/api/catalog.go @@ -0,0 +1,59 @@ +// 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. + +package api + +import ( + "context" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/api/proto" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/dal" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/dal/model" + "github.com/gogf/gf/util/gconv" +) + +type catalogImpl struct { + proto.UnimplementedCatalogServer + catalogDAL dal.CatalogDAL +} + +func NewCatalogImpl() proto.CatalogServer { + var c catalogImpl + c.catalogDAL = dal.NewCatalogDAL() + return &c +} + +func (c *catalogImpl) Registry(ctx context.Context, request *proto.RegistryRequest) (*proto.RegistryResponse, error) { + var rsp = &proto.RegistryResponse{} + if len(request.Definition) == 0 { + return rsp, nil + } + if err := c.catalogDAL.Save(ctx, &model.Event{Definition: request.Definition}); err != nil { + return rsp, err + } + return rsp, nil +} + +func (c *catalogImpl) QueryOperations(ctx context.Context, in *proto.QueryOperationsRequest) (*proto. + QueryOperationsResponse, error) { + var rsp = &proto.QueryOperationsResponse{} + res, err := c.catalogDAL.SelectOperations(ctx, in.ServiceName, in.OperationId) + if err != nil { + return rsp, err + } + if err = gconv.Structs(res, &rsp.Operations); err != nil { + return nil, err + } + return rsp, nil +} diff --git a/eventmesh-catalog-go/api/proto/catalog.pb.go b/eventmesh-catalog-go/api/proto/catalog.pb.go new file mode 100644 index 0000000000..774380c8b9 --- /dev/null +++ b/eventmesh-catalog-go/api/proto/catalog.pb.go @@ -0,0 +1,475 @@ +// +// 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.17.3 +// source: catalog.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type RegistryRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FileName string `protobuf:"bytes,1,opt,name=file_name,json=fileName,proto3" json:"file_name,omitempty"` + Definition string `protobuf:"bytes,2,opt,name=definition,proto3" json:"definition,omitempty"` +} + +func (x *RegistryRequest) Reset() { + *x = RegistryRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_catalog_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegistryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegistryRequest) ProtoMessage() {} + +func (x *RegistryRequest) ProtoReflect() protoreflect.Message { + mi := &file_catalog_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegistryRequest.ProtoReflect.Descriptor instead. +func (*RegistryRequest) Descriptor() ([]byte, []int) { + return file_catalog_proto_rawDescGZIP(), []int{0} +} + +func (x *RegistryRequest) GetFileName() string { + if x != nil { + return x.FileName + } + return "" +} + +func (x *RegistryRequest) GetDefinition() string { + if x != nil { + return x.Definition + } + return "" +} + +type RegistryResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RegistryResponse) Reset() { + *x = RegistryResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_catalog_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegistryResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegistryResponse) ProtoMessage() {} + +func (x *RegistryResponse) ProtoReflect() protoreflect.Message { + mi := &file_catalog_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegistryResponse.ProtoReflect.Descriptor instead. +func (*RegistryResponse) Descriptor() ([]byte, []int) { + return file_catalog_proto_rawDescGZIP(), []int{1} +} + +type QueryOperationsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ServiceName string `protobuf:"bytes,1,opt,name=service_name,json=serviceName,proto3" json:"service_name,omitempty"` + OperationId string `protobuf:"bytes,2,opt,name=operation_id,json=operationId,proto3" json:"operation_id,omitempty"` +} + +func (x *QueryOperationsRequest) Reset() { + *x = QueryOperationsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_catalog_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryOperationsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryOperationsRequest) ProtoMessage() {} + +func (x *QueryOperationsRequest) ProtoReflect() protoreflect.Message { + mi := &file_catalog_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryOperationsRequest.ProtoReflect.Descriptor instead. +func (*QueryOperationsRequest) Descriptor() ([]byte, []int) { + return file_catalog_proto_rawDescGZIP(), []int{2} +} + +func (x *QueryOperationsRequest) GetServiceName() string { + if x != nil { + return x.ServiceName + } + return "" +} + +func (x *QueryOperationsRequest) GetOperationId() string { + if x != nil { + return x.OperationId + } + return "" +} + +type Operation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ChannelName string `protobuf:"bytes,1,opt,name=channel_name,json=channelName,proto3" json:"channel_name,omitempty"` + Schema string `protobuf:"bytes,2,opt,name=schema,proto3" json:"schema,omitempty"` + // publish/subscribe + Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` +} + +func (x *Operation) Reset() { + *x = Operation{} + if protoimpl.UnsafeEnabled { + mi := &file_catalog_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Operation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Operation) ProtoMessage() {} + +func (x *Operation) ProtoReflect() protoreflect.Message { + mi := &file_catalog_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Operation.ProtoReflect.Descriptor instead. +func (*Operation) Descriptor() ([]byte, []int) { + return file_catalog_proto_rawDescGZIP(), []int{3} +} + +func (x *Operation) GetChannelName() string { + if x != nil { + return x.ChannelName + } + return "" +} + +func (x *Operation) GetSchema() string { + if x != nil { + return x.Schema + } + return "" +} + +func (x *Operation) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +type QueryOperationsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Operations []*Operation `protobuf:"bytes,1,rep,name=operations,proto3" json:"operations,omitempty"` +} + +func (x *QueryOperationsResponse) Reset() { + *x = QueryOperationsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_catalog_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryOperationsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryOperationsResponse) ProtoMessage() {} + +func (x *QueryOperationsResponse) ProtoReflect() protoreflect.Message { + mi := &file_catalog_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryOperationsResponse.ProtoReflect.Descriptor instead. +func (*QueryOperationsResponse) Descriptor() ([]byte, []int) { + return file_catalog_proto_rawDescGZIP(), []int{4} +} + +func (x *QueryOperationsResponse) GetOperations() []*Operation { + if x != nil { + return x.Operations + } + return nil +} + +var File_catalog_proto protoreflect.FileDescriptor + +var file_catalog_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x1e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, + 0x6f, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, + 0x4e, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, + 0x12, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x5e, 0x0a, 0x16, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, + 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x22, 0x5a, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, + 0x64, 0x0a, 0x17, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x6f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, + 0x6f, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, + 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x32, 0x81, 0x02, 0x0a, 0x07, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, + 0x67, 0x12, 0x6f, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x12, 0x2f, 0x2e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, + 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, + 0x6f, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x84, 0x01, 0x0a, 0x0f, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x36, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x6d, 0x65, + 0x73, 0x68, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, + 0x6f, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x93, 0x01, 0x0a, 0x33, 0x6f, 0x72, + 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x6d, 0x65, + 0x73, 0x68, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x73, 0x42, 0x14, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x6d, 0x65, 0x73, 0x68, 0x43, 0x61, 0x74, 0x61, + 0x6c, 0x6f, 0x67, 0x47, 0x72, 0x70, 0x63, 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2f, 0x69, 0x6e, 0x63, + 0x75, 0x62, 0x61, 0x74, 0x6f, 0x72, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x6d, 0x65, 0x73, 0x68, + 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x6d, 0x65, 0x73, 0x68, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, + 0x6f, 0x67, 0x2d, 0x67, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_catalog_proto_rawDescOnce sync.Once + file_catalog_proto_rawDescData = file_catalog_proto_rawDesc +) + +func file_catalog_proto_rawDescGZIP() []byte { + file_catalog_proto_rawDescOnce.Do(func() { + file_catalog_proto_rawDescData = protoimpl.X.CompressGZIP(file_catalog_proto_rawDescData) + }) + return file_catalog_proto_rawDescData +} + +var file_catalog_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_catalog_proto_goTypes = []interface{}{ + (*RegistryRequest)(nil), // 0: eventmesh.catalog.api.protocol.RegistryRequest + (*RegistryResponse)(nil), // 1: eventmesh.catalog.api.protocol.RegistryResponse + (*QueryOperationsRequest)(nil), // 2: eventmesh.catalog.api.protocol.QueryOperationsRequest + (*Operation)(nil), // 3: eventmesh.catalog.api.protocol.Operation + (*QueryOperationsResponse)(nil), // 4: eventmesh.catalog.api.protocol.QueryOperationsResponse +} +var file_catalog_proto_depIdxs = []int32{ + 3, // 0: eventmesh.catalog.api.protocol.QueryOperationsResponse.operations:type_name -> eventmesh.catalog.api.protocol.Operation + 0, // 1: eventmesh.catalog.api.protocol.Catalog.Registry:input_type -> eventmesh.catalog.api.protocol.RegistryRequest + 2, // 2: eventmesh.catalog.api.protocol.Catalog.QueryOperations:input_type -> eventmesh.catalog.api.protocol.QueryOperationsRequest + 1, // 3: eventmesh.catalog.api.protocol.Catalog.Registry:output_type -> eventmesh.catalog.api.protocol.RegistryResponse + 4, // 4: eventmesh.catalog.api.protocol.Catalog.QueryOperations:output_type -> eventmesh.catalog.api.protocol.QueryOperationsResponse + 3, // [3:5] is the sub-list for method output_type + 1, // [1:3] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_catalog_proto_init() } +func file_catalog_proto_init() { + if File_catalog_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_catalog_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegistryRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_catalog_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegistryResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_catalog_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryOperationsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_catalog_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Operation); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_catalog_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryOperationsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_catalog_proto_rawDesc, + NumEnums: 0, + NumMessages: 5, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_catalog_proto_goTypes, + DependencyIndexes: file_catalog_proto_depIdxs, + MessageInfos: file_catalog_proto_msgTypes, + }.Build() + File_catalog_proto = out.File + file_catalog_proto_rawDesc = nil + file_catalog_proto_goTypes = nil + file_catalog_proto_depIdxs = nil +} diff --git a/eventmesh-catalog-go/api/proto/catalog.proto b/eventmesh-catalog-go/api/proto/catalog.proto new file mode 100644 index 0000000000..a5633d91e6 --- /dev/null +++ b/eventmesh-catalog-go/api/proto/catalog.proto @@ -0,0 +1,55 @@ +/* + * 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. + */ + +syntax = "proto3"; + +package eventmesh.catalog.api.protocol; + +option java_multiple_files = true; +option java_package="org.apache.eventmesh.common.protocol.catalog.protos"; +option java_outer_classname = "EventmeshCatalogGrpc"; + +option go_package = "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/api/proto"; + +service Catalog { + rpc Registry (RegistryRequest) returns (RegistryResponse) {} + rpc QueryOperations (QueryOperationsRequest) returns (QueryOperationsResponse) {} +} + +message RegistryRequest { + string file_name = 1; + string definition = 2; +} + +message RegistryResponse { +} + +message QueryOperationsRequest { + string service_name = 1; + string operation_id = 2; +} + +message Operation { + string channel_name = 1; + string schema = 2; + // publish/subscribe + string type = 3; +} + +message QueryOperationsResponse { + repeated Operation operations = 1; +} \ No newline at end of file diff --git a/eventmesh-catalog-go/api/proto/catalog_grpc.pb.go b/eventmesh-catalog-go/api/proto/catalog_grpc.pb.go new file mode 100644 index 0000000000..a740cd9402 --- /dev/null +++ b/eventmesh-catalog-go/api/proto/catalog_grpc.pb.go @@ -0,0 +1,157 @@ +// +// 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. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.17.3 +// source: catalog.proto + +package proto + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// CatalogClient is the client API for Catalog service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type CatalogClient interface { + Registry(ctx context.Context, in *RegistryRequest, opts ...grpc.CallOption) (*RegistryResponse, error) + QueryOperations(ctx context.Context, in *QueryOperationsRequest, opts ...grpc.CallOption) (*QueryOperationsResponse, error) +} + +type catalogClient struct { + cc grpc.ClientConnInterface +} + +func NewCatalogClient(cc grpc.ClientConnInterface) CatalogClient { + return &catalogClient{cc} +} + +func (c *catalogClient) Registry(ctx context.Context, in *RegistryRequest, opts ...grpc.CallOption) (*RegistryResponse, error) { + out := new(RegistryResponse) + err := c.cc.Invoke(ctx, "/eventmesh.catalog.api.protocol.Catalog/Registry", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *catalogClient) QueryOperations(ctx context.Context, in *QueryOperationsRequest, opts ...grpc.CallOption) (*QueryOperationsResponse, error) { + out := new(QueryOperationsResponse) + err := c.cc.Invoke(ctx, "/eventmesh.catalog.api.protocol.Catalog/QueryOperations", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// CatalogServer is the server API for Catalog service. +// All implementations must embed UnimplementedCatalogServer +// for forward compatibility +type CatalogServer interface { + Registry(context.Context, *RegistryRequest) (*RegistryResponse, error) + QueryOperations(context.Context, *QueryOperationsRequest) (*QueryOperationsResponse, error) + mustEmbedUnimplementedCatalogServer() +} + +// UnimplementedCatalogServer must be embedded to have forward compatible implementations. +type UnimplementedCatalogServer struct { +} + +func (UnimplementedCatalogServer) Registry(context.Context, *RegistryRequest) (*RegistryResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Registry not implemented") +} +func (UnimplementedCatalogServer) QueryOperations(context.Context, *QueryOperationsRequest) (*QueryOperationsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryOperations not implemented") +} +func (UnimplementedCatalogServer) mustEmbedUnimplementedCatalogServer() {} + +// UnsafeCatalogServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to CatalogServer will +// result in compilation errors. +type UnsafeCatalogServer interface { + mustEmbedUnimplementedCatalogServer() +} + +func RegisterCatalogServer(s grpc.ServiceRegistrar, srv CatalogServer) { + s.RegisterService(&Catalog_ServiceDesc, srv) +} + +func _Catalog_Registry_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RegistryRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CatalogServer).Registry(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/eventmesh.catalog.api.protocol.Catalog/Registry", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CatalogServer).Registry(ctx, req.(*RegistryRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Catalog_QueryOperations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryOperationsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CatalogServer).QueryOperations(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/eventmesh.catalog.api.protocol.Catalog/QueryOperations", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CatalogServer).QueryOperations(ctx, req.(*QueryOperationsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Catalog_ServiceDesc is the grpc.ServiceDesc for Catalog service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Catalog_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "eventmesh.catalog.api.protocol.Catalog", + HandlerType: (*CatalogServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Registry", + Handler: _Catalog_Registry_Handler, + }, + { + MethodName: "QueryOperations", + Handler: _Catalog_QueryOperations_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "catalog.proto", +} diff --git a/eventmesh-catalog-go/bin/start-catalog.sh b/eventmesh-catalog-go/bin/start-catalog.sh new file mode 100644 index 0000000000..3a4821e9af --- /dev/null +++ b/eventmesh-catalog-go/bin/start-catalog.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# +# Licensed to 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. Apache Software Foundation (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. + +CATALOG_HOME=`cd $(dirname $0)/.. && pwd` +export CATALOG_HOME +export CATALOG_LOG_HOME=${CATALOG_HOME}/logs +echo "CATALOG_HOME : ${CATALOG_HOME}, CATALOG_LOG_HOME : ${CATALOG_LOG_HOME}" + +serverLogFile=${CATALOG_HOME}/logs/catalog.log +serverHistoryLogFile=${CATALOG_HOME}/catalogHistory.log +pidConf=${CATALOG_HOME}/bin/pid.conf +serverName="eventmesh-catalog" +startScriptName="start-catalog.sh" + +function make_logs_dir { + if [ ! -e "${CATALOG_LOG_HOME}" ]; then mkdir -p "${CATALOG_LOG_HOME}"; fi +} + +make_logs_dir + +#check process +num=`ps -ef |grep ${serverName} |grep -v grep|wc -l` +echo "`date` the num of process is $num" +if [ $num -gt 0 ];then + echo "the process is exist now " + exit 0 +fi + +#start process +nohup ./${serverName} 2>&1 | tee $serverLogFile>>$serverHistoryLogFile 2>&1 & +sleep 3 + +num=`ps -ef | grep ${serverName} | grep -v grep | wc -l` +echo "the num of process after start is $num" +if [ $num -lt 1 ];then + echo "the process is not exit after start " + exit 9 +fi + +pid=`ps -ef |grep ${serverName} |grep -v grep|head -n 1 |awk '{print $2}'` +echo $pid>$pidConf +exit 0 \ No newline at end of file diff --git a/eventmesh-catalog-go/bin/stop-catalog.sh b/eventmesh-catalog-go/bin/stop-catalog.sh new file mode 100644 index 0000000000..c634172a2d --- /dev/null +++ b/eventmesh-catalog-go/bin/stop-catalog.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# +# Licensed to 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. Apache Software Foundation (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. + +serverName="eventmesh-catalog" + +#stop process +pidInfo=$(ps -ef | grep ${serverName} | grep -v grep | awk '{print $2}') +echo "`date` the pid info is $pidInfo" + +for pid in $pidInfo;do + kill -9 $pid +done + +sleep 3 + +#check process num +num=$(ps -ef | grep ${serverName} | grep -v grep |wc -l) + +if [ $num -gt 0 ];then + echo "`date` after stop process in force way the processNum is $num still bigger than 0" + exit 9 +fi +exit 0 \ No newline at end of file diff --git a/eventmesh-catalog-go/cmd/controller/catalog.go b/eventmesh-catalog-go/cmd/controller/catalog.go new file mode 100644 index 0000000000..9339f10a35 --- /dev/null +++ b/eventmesh-catalog-go/cmd/controller/catalog.go @@ -0,0 +1,117 @@ +// 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. + +package main + +import ( + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/dal" + "github.com/gin-gonic/gin" + "github.com/gogf/gf/util/gconv" + "net/http" +) + +const ( + eventIDParam = "eventId" +) + +// CatalogController workflow controller operations +type CatalogController struct { + catalogDAL dal.CatalogDAL +} + +func NewCatalogController() *CatalogController { + c := CatalogController{} + c.catalogDAL = dal.NewCatalogDAL() + return &c +} + +// Save save event catalog data +// @Summary save event catalog +// @Description save event catalog +// @Tags Catalog +// @Accept json +// @Produce json +// @Param request body SaveEventRequest true "event catalog data" +// @Success 200 +// @Failure 400 +// @Failure 404 +// @Failure 500 +// @Router /catalog [post] +func (c *CatalogController) Save(ctx *gin.Context) { + request := SaveEventRequest{} + if err := ctx.ShouldBind(&request); err != nil { + ctx.JSON(http.StatusBadRequest, err.Error()) + return + } + if err := c.catalogDAL.Save(ctx, &request.Event); err != nil { + ctx.JSON(http.StatusInternalServerError, err.Error()) + return + } + ctx.JSON(http.StatusOK, nil) +} + +// QueryList query event catalog list +// @Summary query event catalog list +// @Description query event catalog list +// @Tags Catalog +// @Accept json +// @Produce json +// @Param page query string false "query page" +// @Param size query string false "query size" +// @Success 200 {object} QueryEventsResponse +// @Failure 400 +// @Failure 404 +// @Failure 500 +// @Router /catalog [get] +func (c *CatalogController) QueryList(ctx *gin.Context) { + request := QueryEventsRequest{} + if err := ctx.ShouldBind(&request); err != nil { + ctx.JSON(http.StatusBadRequest, err.Error()) + return + } + res, total, err := c.catalogDAL.SelectList(ctx, request.Page, request.Size) + if err != nil { + ctx.JSON(http.StatusInternalServerError, err.Error()) + return + } + ctx.JSON(http.StatusOK, &QueryEventsResponse{Total: total, Events: res}) +} + +// QueryDetail query event catalog detail info +// @Summary query event catalog detail info +// @Description query event catalog detail info +// @Tags Catalog +// @Accept json +// @Produce json +// @Param eventId path string true "event id" +// @Success 200 {object} QueryEventResponse +// @Failure 400 +// @Failure 404 +// @Failure 500 +// @Router /catalog/{eventId} [get] +func (c *CatalogController) QueryDetail(ctx *gin.Context) { + eventID := gconv.Int(ctx.Param(eventIDParam)) + res, err := c.catalogDAL.Select(ctx, eventID) + if err != nil { + ctx.JSON(http.StatusInternalServerError, err.Error()) + return + } + if res == nil { + ctx.JSON(http.StatusOK, nil) + return + } + ctx.JSON(http.StatusOK, &QueryEventResponse{Event: *res}) + return +} diff --git a/eventmesh-catalog-go/cmd/controller/docs/docs.go b/eventmesh-catalog-go/cmd/controller/docs/docs.go new file mode 100644 index 0000000000..05c922a13e --- /dev/null +++ b/eventmesh-catalog-go/cmd/controller/docs/docs.go @@ -0,0 +1,242 @@ +// 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. + +// Package docs GENERATED BY SWAG; DO NOT EDIT +// This file was generated by swaggo/swag +package docs + +import "github.com/swaggo/swag" + +const docTemplate = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "contact": {}, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/catalog": { + "get": { + "description": "query event catalog list", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Catalog" + ], + "summary": "query event catalog list", + "parameters": [ + { + "type": "string", + "description": "query page", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "query size", + "name": "size", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/main.QueryEventsResponse" + } + }, + "400": { + "description": "Bad Request" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "Internal Server Error" + } + } + }, + "post": { + "description": "save event catalog", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Catalog" + ], + "summary": "save event catalog", + "parameters": [ + { + "description": "event catalog data", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/main.SaveEventRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad Request" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/{eventId}": { + "get": { + "description": "query event catalog detail info", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Catalog" + ], + "summary": "query event catalog detail info", + "parameters": [ + { + "type": "string", + "description": "event id", + "name": "eventId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/main.QueryEventResponse" + } + }, + "400": { + "description": "Bad Request" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "Internal Server Error" + } + } + } + } + }, + "definitions": { + "main.QueryEventResponse": { + "type": "object", + "properties": { + "event": { + "$ref": "#/definitions/model.Event" + } + } + }, + "main.QueryEventsResponse": { + "type": "object", + "properties": { + "events": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Event" + } + }, + "total": { + "description": "total count", + "type": "integer" + } + } + }, + "main.SaveEventRequest": { + "type": "object", + "properties": { + "event": { + "$ref": "#/definitions/model.Event" + } + } + }, + "model.Event": { + "type": "object", + "properties": { + "create_time": { + "type": "string" + }, + "definition": { + "type": "string" + }, + "file_name": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "update_time": { + "type": "string" + }, + "version": { + "type": "string" + } + } + } + } +}` + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = &swag.Spec{ + Version: "1.0", + Host: "", + BasePath: "", + Schemes: []string{}, + Title: "Event Catalog API", + Description: "This is a event catalog server.", + InfoInstanceName: "swagger", + SwaggerTemplate: docTemplate, +} + +func init() { + swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) +} diff --git a/eventmesh-catalog-go/cmd/controller/docs/swagger.json b/eventmesh-catalog-go/cmd/controller/docs/swagger.json new file mode 100644 index 0000000000..f1aa471326 --- /dev/null +++ b/eventmesh-catalog-go/cmd/controller/docs/swagger.json @@ -0,0 +1,217 @@ +// 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. + +{ + "swagger": "2.0", + "info": { + "description": "This is a event catalog server.", + "title": "Event Catalog API", + "contact": {}, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0" + }, + "paths": { + "/catalog": { + "get": { + "description": "query event catalog list", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Catalog" + ], + "summary": "query event catalog list", + "parameters": [ + { + "type": "string", + "description": "query page", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "query size", + "name": "size", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/main.QueryEventsResponse" + } + }, + "400": { + "description": "Bad Request" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "Internal Server Error" + } + } + }, + "post": { + "description": "save event catalog", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Catalog" + ], + "summary": "save event catalog", + "parameters": [ + { + "description": "event catalog data", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/main.SaveEventRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad Request" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/{eventId}": { + "get": { + "description": "query event catalog detail info", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Catalog" + ], + "summary": "query event catalog detail info", + "parameters": [ + { + "type": "string", + "description": "event id", + "name": "eventId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/main.QueryEventResponse" + } + }, + "400": { + "description": "Bad Request" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "Internal Server Error" + } + } + } + } + }, + "definitions": { + "main.QueryEventResponse": { + "type": "object", + "properties": { + "event": { + "$ref": "#/definitions/model.Event" + } + } + }, + "main.QueryEventsResponse": { + "type": "object", + "properties": { + "events": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Event" + } + }, + "total": { + "description": "total count", + "type": "integer" + } + } + }, + "main.SaveEventRequest": { + "type": "object", + "properties": { + "event": { + "$ref": "#/definitions/model.Event" + } + } + }, + "model.Event": { + "type": "object", + "properties": { + "create_time": { + "type": "string" + }, + "definition": { + "type": "string" + }, + "file_name": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "update_time": { + "type": "string" + }, + "version": { + "type": "string" + } + } + } + } +} \ No newline at end of file diff --git a/eventmesh-catalog-go/cmd/controller/docs/swagger.yaml b/eventmesh-catalog-go/cmd/controller/docs/swagger.yaml new file mode 100644 index 0000000000..2984b7ec4d --- /dev/null +++ b/eventmesh-catalog-go/cmd/controller/docs/swagger.yaml @@ -0,0 +1,148 @@ +# +# 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. + +definitions: + main.QueryEventResponse: + properties: + event: + $ref: '#/definitions/model.Event' + type: object + main.QueryEventsResponse: + properties: + events: + items: + $ref: '#/definitions/model.Event' + type: array + total: + description: total count + type: integer + type: object + main.SaveEventRequest: + properties: + event: + $ref: '#/definitions/model.Event' + type: object + model.Event: + properties: + create_time: + type: string + definition: + type: string + file_name: + type: string + id: + type: integer + status: + type: integer + title: + type: string + update_time: + type: string + version: + type: string + type: object +info: + contact: {} + description: This is a event catalog server. + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + title: Event Catalog API + version: "1.0" +paths: + /catalog: + get: + consumes: + - application/json + description: query event catalog list + parameters: + - description: query page + in: query + name: page + type: string + - description: query size + in: query + name: size + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/main.QueryEventsResponse' + "400": + description: Bad Request + "404": + description: Not Found + "500": + description: Internal Server Error + summary: query event catalog list + tags: + - Catalog + post: + consumes: + - application/json + description: save event catalog + parameters: + - description: event catalog data + in: body + name: request + required: true + schema: + $ref: '#/definitions/main.SaveEventRequest' + produces: + - application/json + responses: + "200": + description: OK + "400": + description: Bad Request + "404": + description: Not Found + "500": + description: Internal Server Error + summary: save event catalog + tags: + - Catalog + /catalog/{eventId}: + get: + consumes: + - application/json + description: query event catalog detail info + parameters: + - description: event id + in: path + name: eventId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/main.QueryEventResponse' + "400": + description: Bad Request + "404": + description: Not Found + "500": + description: Internal Server Error + summary: query event catalog detail info + tags: + - Catalog +swagger: "2.0" diff --git a/eventmesh-catalog-go/cmd/controller/main.go b/eventmesh-catalog-go/cmd/controller/main.go new file mode 100644 index 0000000000..fd38c038c9 --- /dev/null +++ b/eventmesh-catalog-go/cmd/controller/main.go @@ -0,0 +1,119 @@ +// 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. + +package main + +import ( + "fmt" + _ "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/cmd/controller/docs" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/dal" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/util" + "github.com/apache/incubator-eventmesh/eventmesh-server-go/config" + "github.com/gin-gonic/gin" + swaggerFiles "github.com/swaggo/files" + ginSwagger "github.com/swaggo/gin-swagger" + "log" + "net/http" +) + +type Server struct { + server *gin.Engine + catalog *CatalogController +} + +// @title Event Catalog API +// @version 1.0 +// @description This is a event catalog server. + +// @license.name Apache 2.0 +// @license.url http://www.apache.org/licenses/LICENSE-2.0.html +func main() { + s, err := initServer() + if err != nil { + log.Fatal("new server fail: " + err.Error()) + } + s.router() + if err := s.run(); err != nil { + log.Fatal("run server fail: " + err.Error()) + } +} + +func initServer() (*Server, error) { + var s Server + if err := s.setupConfig(); err != nil { + return nil, err + } + if err := dal.Open(); err != nil { + return nil, err + } + r := gin.New() + r.Use(cors()).Use(gin.Recovery()) + swagger(r) + s.server = r + s.catalog = NewCatalogController() + return &s, nil +} + +func cors() gin.HandlerFunc { + return func(c *gin.Context) { + method := c.Request.Method + origin := c.Request.Header.Get("Origin") + if origin != "" { + c.Header("Access-Control-Allow-Origin", "*") + c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") + c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, "+ + "Authorization") + c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, "+ + "Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type") + c.Header("Access-Control-Allow-Credentials", "true") + } + if method == "OPTIONS" { + c.AbortWithStatus(http.StatusNoContent) + } + c.Next() + } +} + +func swagger(r *gin.Engine) { + r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) +} + +func (s *Server) router() { + s.server.POST("/catalog", s.catalog.Save) + s.server.GET("/catalog", s.catalog.QueryList) + s.server.GET("/catalog/:eventId", s.catalog.QueryDetail) +} + +func (s *Server) setupConfig() error { + config.ServerConfigPath = "./configs/controller.yaml" + // compatible local environment + if !util.Exists(config.ServerConfigPath) { + config.ServerConfigPath = "../configs/controller.yaml" + } + // compatible deploy environment + if !util.Exists(config.ServerConfigPath) { + config.ServerConfigPath = "../conf/controller.yaml" + } + cfg, err := config.LoadConfig(config.ServerConfigPath) + if err != nil { + return err + } + config.SetGlobalConfig(cfg) + return config.Setup(cfg) +} + +func (s *Server) run() error { + return s.server.Run(fmt.Sprintf(":%d", config.GlobalConfig().Server.Port)) +} diff --git a/eventmesh-catalog-go/cmd/controller/request.go b/eventmesh-catalog-go/cmd/controller/request.go new file mode 100644 index 0000000000..165a0a9f03 --- /dev/null +++ b/eventmesh-catalog-go/cmd/controller/request.go @@ -0,0 +1,29 @@ +// 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. + +package main + +import "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/dal/model" + +// SaveEventRequest save event request body +type SaveEventRequest struct { + Event model.Event `json:"event"` +} + +// QueryEventsRequest query events request body +type QueryEventsRequest struct { + Page int `form:"page" json:"page"` // page num + Size int `form:"size" json:"size"` // page size +} diff --git a/eventmesh-catalog-go/cmd/controller/response.go b/eventmesh-catalog-go/cmd/controller/response.go new file mode 100644 index 0000000000..00740e3c46 --- /dev/null +++ b/eventmesh-catalog-go/cmd/controller/response.go @@ -0,0 +1,29 @@ +// 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. + +package main + +import "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/dal/model" + +// QueryEventsResponse query events response data +type QueryEventsResponse struct { + Events []model.Event `json:"events"` + Total int `json:"total"` // total count +} + +// QueryEventResponse query event detail response data +type QueryEventResponse struct { + Event model.Event `json:"event"` +} diff --git a/eventmesh-catalog-go/config/config.go b/eventmesh-catalog-go/config/config.go new file mode 100644 index 0000000000..75164a0933 --- /dev/null +++ b/eventmesh-catalog-go/config/config.go @@ -0,0 +1,28 @@ +// 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. + +package config + +import ( + "github.com/apache/incubator-eventmesh/eventmesh-server-go/plugin" +) + +type Config struct { + Server struct { + Port uint16 `yaml:"port"` + Name string `yaml:"name"` + } + Plugins plugin.Config `yaml:"plugins,omitempty"` +} diff --git a/eventmesh-catalog-go/configs/catalog.yaml b/eventmesh-catalog-go/configs/catalog.yaml new file mode 100644 index 0000000000..910fb63806 --- /dev/null +++ b/eventmesh-catalog-go/configs/catalog.yaml @@ -0,0 +1,44 @@ +# +# 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. + +server: + port: 12012 + name: "EVENTMESH-catalog" +plugins: + registry: + nacos: + address_list: "127.0.0.1:8848" + selector: + nacos: + address_list: "127.0.0.1:8848" + database: + mysql: + dsn: "root:123456@(127.0.0.1:3306)/db_catalog?charset=utf8&parseTime=True&loc=Local" + max_idle: 50 + max_open: 100 + max_lifetime: 180000 + log: + default: + - writer: console + level: debug + - writer: file + level: info + writer_config: + filename: ./catalog.log + max_size: 10 + max_backups: 10 + max_age: 7 + compress: false \ No newline at end of file diff --git a/eventmesh-catalog-go/configs/controller.yaml b/eventmesh-catalog-go/configs/controller.yaml new file mode 100644 index 0000000000..6c922f9d43 --- /dev/null +++ b/eventmesh-catalog-go/configs/controller.yaml @@ -0,0 +1,35 @@ +# +# 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. + +server: + port: 12013 +plugins: + database: + mysql: + dsn: "root:123456@(127.0.0.1:3306)/db_catalog?charset=utf8&parseTime=True&loc=Local" + max_idle: 50 + max_open: 100 + max_lifetime: 180000 + log: + default: + - writer: file + level: info + writer_config: + filename: ./workflow.log + max_size: 10 + max_backups: 10 + max_age: 7 + compress: false \ No newline at end of file diff --git a/eventmesh-catalog-go/configs/testexpress.yaml b/eventmesh-catalog-go/configs/testexpress.yaml new file mode 100644 index 0000000000..f7b1726461 --- /dev/null +++ b/eventmesh-catalog-go/configs/testexpress.yaml @@ -0,0 +1,40 @@ +# +# 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. + +asyncapi: 2.3.0 +info: + title: expressapp + version: '0.1.0' +channels: + express/create: + publish: + operationId: sendExpress + message: + $ref: '#/components/messages/Order' + subscribe: + operationId: receiveExpress + message: + $ref: '#/components/messages/Order' +components: + messages: + Order: + payload: + type: object + properties: + orderNo: + type: string + Amount: + type: string \ No newline at end of file diff --git a/eventmesh-catalog-go/configs/testorder.yaml b/eventmesh-catalog-go/configs/testorder.yaml new file mode 100644 index 0000000000..9a00efbc6a --- /dev/null +++ b/eventmesh-catalog-go/configs/testorder.yaml @@ -0,0 +1,40 @@ +# +# 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. + +asyncapi: 2.3.0 +info: + title: orderapp + version: '0.1.0' +channels: + order/create: + publish: + operationId: sendOrder + message: + $ref: '#/components/messages/Order' + subscribe: + operationId: receiveOrder + message: + $ref: '#/components/messages/Order' +components: + messages: + Order: + payload: + type: object + properties: + orderNo: + type: string + Amount: + type: string \ No newline at end of file diff --git a/eventmesh-catalog-go/configs/testpayment.yaml b/eventmesh-catalog-go/configs/testpayment.yaml new file mode 100644 index 0000000000..2525f27a4e --- /dev/null +++ b/eventmesh-catalog-go/configs/testpayment.yaml @@ -0,0 +1,40 @@ +# +# 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. + +asyncapi: 2.3.0 +info: + title: paymentapp + version: '0.1.0' +channels: + payment/create: + publish: + operationId: sendPayment + message: + $ref: '#/components/messages/Order' + subscribe: + operationId: receivePayment + message: + $ref: '#/components/messages/Order' +components: + messages: + Order: + payload: + type: object + properties: + orderNo: + type: string + Amount: + type: string \ No newline at end of file diff --git a/eventmesh-catalog-go/distribution/mysql-schema.sql b/eventmesh-catalog-go/distribution/mysql-schema.sql new file mode 100644 index 0000000000..f79e945584 --- /dev/null +++ b/eventmesh-catalog-go/distribution/mysql-schema.sql @@ -0,0 +1,54 @@ +/* + * 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. + */ + +create database if not exists db_catalog; + +use db_catalog; + +create table if not exists t_event +( + id int auto_increment comment '主键、自增' + primary key, + title varchar(1024) not null, + file_name varchar(1024) not null, + definition text not null, + status int not null, + version varchar(64) not null, + create_time datetime default CURRENT_TIMESTAMP not null, + update_time datetime default CURRENT_TIMESTAMP not null, + index `index_title` (title) +) + collate = utf8mb3_bin; + +create table if not exists t_event_catalog +( + id int auto_increment comment '主键、自增' + primary key, + service_name varchar(256) default '' not null comment '服务名称', + operation_id varchar(1024) not null, + channel_name varchar(1024) not null, + type varchar(1024) not null, + `schema` text not null, + status int not null, + create_time datetime default CURRENT_TIMESTAMP not null, + update_time datetime default CURRENT_TIMESTAMP not null, + index `index_service_name` (service_name), + index `index_channel_name` (channel_name), + index `index_operation_id` (operation_id) + ) + collate = utf8mb3_bin; + diff --git a/eventmesh-catalog-go/go.mod b/eventmesh-catalog-go/go.mod new file mode 100644 index 0000000000..d4755b68ac --- /dev/null +++ b/eventmesh-catalog-go/go.mod @@ -0,0 +1,38 @@ +// 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. + +module github.com/apache/incubator-eventmesh/eventmesh-catalog-go + +go 1.16 + +require ( + github.com/apache/incubator-eventmesh/eventmesh-server-go v0.0.0-20220812021948-0945ab92daea + github.com/asyncapi/parser-go v0.4.2 + github.com/gogf/gf v1.16.9 + github.com/mitchellh/mapstructure v1.5.0 + github.com/pkg/errors v0.9.1 + google.golang.org/grpc v1.48.0 + google.golang.org/protobuf v1.28.1 + gorm.io/driver/mysql v1.3.5 + gorm.io/gorm v1.23.8 +) + +require ( + github.com/gin-gonic/gin v1.8.2 + github.com/nacos-group/nacos-sdk-go/v2 v2.0.4 // indirect + github.com/swaggo/files v1.0.0 + github.com/swaggo/gin-swagger v1.5.3 + github.com/swaggo/swag v1.8.9 // indirect +) diff --git a/eventmesh-catalog-go/go.sum b/eventmesh-catalog-go/go.sum new file mode 100644 index 0000000000..16cd760461 --- /dev/null +++ b/eventmesh-catalog-go/go.sum @@ -0,0 +1,807 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= +github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/agiledragon/gomonkey/v2 v2.3.1 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs= +github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDHxfTGEciD+yhvOU/5s1Rfk= +github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704 h1:PpfENOj/vPfhhy9N2OFRjpue0hjM5XqAp2thFmkXXIk= +github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/incubator-eventmesh/eventmesh-server-go v0.0.0-20220812021948-0945ab92daea h1:2HgaPliO/+mIcOEY3YXIv+uTyZK+TjXzm+P9rYxACh0= +github.com/apache/incubator-eventmesh/eventmesh-server-go v0.0.0-20220812021948-0945ab92daea/go.mod h1:Z0G6PXEFojRm73fadnqMFuPcaTdIr5s8Bgq/PCKOu40= +github.com/asyncapi/converter-go v0.0.0-20190802111537-d8459b2bd403 h1:HhobldPK/8Cnhliwl744pXSfyjtF956/vOJLyJ8mrXk= +github.com/asyncapi/converter-go v0.0.0-20190802111537-d8459b2bd403/go.mod h1:mpJYWYy+USNiLENQxiyGgRc3qtFPxYSWdSd/eS+R6bo= +github.com/asyncapi/parser-go v0.4.2 h1:+PPo+Sk/u9IPH3JklXFrPUQnr9LURwNJU5jfcLBBITc= +github.com/asyncapi/parser-go v0.4.2/go.mod h1:5iAT+irO9xKeBDnIhqT0ev8QJH1dHq4i2oU/UBhhwB8= +github.com/asyncapi/spec-json-schemas/v2 v2.14.0 h1:t5Frb4WzaV2bTlcRqXhBdvqTjO6+n/oiPMjvCxYooag= +github.com/asyncapi/spec-json-schemas/v2 v2.14.0/go.mod h1:5lFCFtRGfI3WVOla4slifjgPs9x79FY0fqZjgNL495c= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 h1:LdXxtjzvZYhhUaonAaAKArG3pyC67kGL3YY+6hGG8G4= +github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= +github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= +github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY= +github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= +github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= +github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/gogf/gf v1.16.9 h1:Q803UmmRo59+Ws08sMVFOcd8oNpkSWL9vS33hlo/Cyk= +github.com/gogf/gf v1.16.9/go.mod h1:8Q/kw05nlVRp+4vv7XASBsMe9L1tsVKiGoeP2AHnlkk= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc= +github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0= +github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= +github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ= +github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nacos-group/nacos-sdk-go/v2 v2.0.3/go.mod h1:SlhyCAv961LcZ198XpKfPEQqlJWt2HkL1fDLas0uy/w= +github.com/nacos-group/nacos-sdk-go/v2 v2.0.4 h1:KC2oik+gijh3+S5zTJEGdTOAkpcXW5XqTWiZiAHsxXI= +github.com/nacos-group/nacos-sdk-go/v2 v2.0.4/go.mod h1:ys/1adWeKXXzbNWfRNbaFlX/t6HVLWdpsNDvmoWTw0g= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= +github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE= +github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= +github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= +github.com/swaggo/files v1.0.0 h1:1gGXVIeUFCS/dta17rnP0iOpr6CXFwKD7EO5ID233e4= +github.com/swaggo/files v1.0.0/go.mod h1:N59U6URJLyU1PQgFqPM7wXLMhJx7QAolnvfQkqO13kc= +github.com/swaggo/gin-swagger v1.5.3 h1:8mWmHLolIbrhJJTflsaFoZzRBYVmEE7JZGIq08EiC0Q= +github.com/swaggo/gin-swagger v1.5.3/go.mod h1:3XJKSfHjDMB5dBo/0rrTXidPmgLeqsX89Yp4uA50HpI= +github.com/swaggo/swag v1.8.1 h1:JuARzFX1Z1njbCGz+ZytBR15TFJwF2Q7fu8puJHhQYI= +github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ= +github.com/swaggo/swag v1.8.9 h1:kHtaBe/Ob9AZzAANfcn5c6RyCke9gG9QpH0jky0I/sA= +github.com/swaggo/swag v1.8.9/go.mod h1:ezQVUUhly8dludpVk+/PuwJWvLLanB13ygV5Pr9enSk= +github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA= +github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/otel v1.0.0 h1:qTTn6x71GVBvoafHK/yaRUmFzI4LcONZD0/kXxl5PHI= +go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg= +go.opentelemetry.io/otel/trace v1.0.0 h1:TSBr8GTEtKevYMG/2d21M989r5WJYVimhTHBKVEZuh4= +go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.22.0 h1:Zcye5DUgBloQ9BaT4qc9BnjOFog5TvBSAGkJ3Nf70c0= +go.uber.org/zap v1.22.0/go.mod h1:H4siCOZOrAolnUPJEkfaSjDqyP+BDS0DdDWzwcgt3+U= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ= +golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= +gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.3.5 h1:iWBTVW/8Ij5AG4e0G/zqzaJblYkBI1VIL1LG2HUGsvY= +gorm.io/driver/mysql v1.3.5/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c= +gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE= +gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/eventmesh-catalog-go/internal/catalog.go b/eventmesh-catalog-go/internal/catalog.go new file mode 100644 index 0000000000..7ae7a2b77b --- /dev/null +++ b/eventmesh-catalog-go/internal/catalog.go @@ -0,0 +1,173 @@ +// 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. + +package dal + +import ( + "context" + "fmt" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/constants" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/dal/model" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/util" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/pkg/asyncapi" + v2 "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/pkg/asyncapi/v2" + "github.com/gogf/gf/util/gconv" + "gorm.io/gorm" + "time" +) + +const maxSize = 100 + +type CatalogDAL interface { + Select(ctx context.Context, eventID int) (*model.Event, error) + SelectList(ctx context.Context, page int, size int) ([]model.Event, int, error) + Save(ctx context.Context, record *model.Event) error + SelectOperations(ctx context.Context, serviceName string, operationID string) ([]*model.EventCatalog, error) +} + +func NewCatalogDAL() CatalogDAL { + var w catalogDALImpl + return &w +} + +type catalogDALImpl struct { +} + +func (c *catalogDALImpl) Select(ctx context.Context, eventID int) (*model.Event, error) { + var condition = model.Event{ID: eventID} + var r model.Event + if err := catalogDB.WithContext(ctx).Where(&condition).First(&r).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, err + } + return &r, nil +} + +func (c *catalogDALImpl) SelectList(ctx context.Context, page int, size int) ([]model.Event, int, error) { + var r []model.Event + db := catalogDB.WithContext(ctx).Where("1=1") + db = db.Where("status = ?", constants.NormalStatus) + if size > maxSize { + size = maxSize + } + if page == 0 { + page = 1 + } + var count int64 + db = db.Limit(size).Offset(size * (page - 1)).Order("update_time DESC") + if err := db.Find(&r).Count(&count).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, 0, nil + } + return nil, 0, err + } + return r, int(count), nil + +} + +func (c *catalogDALImpl) SelectOperations(ctx context.Context, serviceName string, + operationID string) ([]*model.EventCatalog, error) { + var res []*model.EventCatalog + var condition = model.EventCatalog{ServiceName: serviceName, OperationID: operationID} + if err := catalogDB.WithContext(ctx).Where(&condition).Find(&res).Error; err != nil { + return nil, err + } + return res, nil +} + +func (c *catalogDALImpl) Save(ctx context.Context, record *model.Event) error { + return catalogDB.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + if record.ID > 0 { + if err := c.delete(tx, record); err != nil { + return err + } + } + return c.create(tx, record) + }) +} + +func (c *catalogDALImpl) insert(tx *gorm.DB, record *model.EventCatalog) error { + return tx.Create(record).Error +} + +func (c *catalogDALImpl) insertEvent(tx *gorm.DB, record *model.Event) error { + return tx.Create(record).Error +} + +func (c *catalogDALImpl) delete(tx *gorm.DB, record *model.Event) error { + var handlers []func() error + handlers = append(handlers, func() error { + cond := model.Event{Status: constants.InvalidStatus, UpdateTime: time.Now()} + return tx.Where("id = ?", record.ID).Updates(&cond).Error + }, func() error { + cond := model.EventCatalog{Status: constants.InvalidStatus, UpdateTime: time.Now()} + return tx.Where("service_name = ?", record.Title).Updates(&cond).Error + }) + return util.GoAndWait(handlers...) +} + +func (c *catalogDALImpl) create(tx *gorm.DB, record *model.Event) error { + if len(record.Definition) == 0 { + return nil + } + var doc = new(v2.Document) + if err := v2.Decode(gconv.Bytes(record.Definition), &doc); err != nil { + return err + } + if len(doc.Channels()) == 0 { + return nil + } + var handlers []func() error + handlers = append(handlers, func() error { + return c.insertEvent(tx, c.buildEvent(record.Definition, doc)) + }) + for _, channel := range doc.Channels() { + for _, operation := range channel.Operations() { + var eventCatalog = c.buildEventCatalog(doc.Info().Title(), channel, operation) + handlers = append(handlers, func() error { + return c.insert(tx, eventCatalog) + }) + } + } + return util.GoAndWait(handlers...) +} + +func (c *catalogDALImpl) buildEventCatalog(serviceName string, channel asyncapi.Channel, + operation asyncapi.Operation) *model.EventCatalog { + var record model.EventCatalog + record.ServiceName = serviceName + record.OperationID = fmt.Sprintf("file://%s.yaml#%s", serviceName, operation.ID()) + record.ChannelName = channel.ID() + record.Type = string(operation.Type()) + record.Status = constants.NormalStatus + record.CreateTime = time.Now() + record.UpdateTime = time.Now() + record.Schema = gconv.String(operation.Messages()[0].Payload()) + return &record +} + +func (c *catalogDALImpl) buildEvent(definition string, doc asyncapi.Document) *model.Event { + var record model.Event + record.Title = doc.Info().Title() + record.FileName = fmt.Sprintf("%s.yaml", record.Title) + record.Definition = definition + record.Status = constants.NormalStatus + record.Version = doc.Info().Version() + record.CreateTime = time.Now() + record.UpdateTime = time.Now() + return &record +} diff --git a/eventmesh-catalog-go/internal/config.go b/eventmesh-catalog-go/internal/config.go new file mode 100644 index 0000000000..f09971a000 --- /dev/null +++ b/eventmesh-catalog-go/internal/config.go @@ -0,0 +1,44 @@ +// 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. + +package dal + +import ( + "database/sql" + "gorm.io/gorm/logger" + "time" + + "gorm.io/driver/mysql" + "gorm.io/gorm" + + pmysql "github.com/apache/incubator-eventmesh/eventmesh-server-go/plugin/database/mysql" +) + +var catalogDB *gorm.DB + +func Open() error { + var err error + d, err := sql.Open("mysql", pmysql.PluginConfig.DSN) + d.SetMaxOpenConns(pmysql.PluginConfig.MaxOpen) + d.SetMaxIdleConns(pmysql.PluginConfig.MaxIdle) + d.SetConnMaxLifetime(time.Millisecond * time.Duration(pmysql.PluginConfig.MaxLifetime)) + + catalogDB, err = gorm.Open(mysql.New(mysql.Config{Conn: d}), + &gorm.Config{Logger: logger.Default.LogMode(logger.Silent)}) + if err != nil { + return err + } + return nil +} diff --git a/eventmesh-catalog-go/internal/constants/constants.go b/eventmesh-catalog-go/internal/constants/constants.go new file mode 100644 index 0000000000..189eee31d1 --- /dev/null +++ b/eventmesh-catalog-go/internal/constants/constants.go @@ -0,0 +1,21 @@ +// 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. + +package constants + +const ( + NormalStatus = 1 + InvalidStatus = -1 +) diff --git a/eventmesh-catalog-go/internal/dal/catalog.go b/eventmesh-catalog-go/internal/dal/catalog.go new file mode 100644 index 0000000000..7609425fb9 --- /dev/null +++ b/eventmesh-catalog-go/internal/dal/catalog.go @@ -0,0 +1,173 @@ +// 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. + +package dal + +import ( + "context" + "fmt" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/constants" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/dal/model" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/util" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/pkg/asyncapi" + v2 "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/pkg/asyncapi/v2" + "github.com/gogf/gf/util/gconv" + "gorm.io/gorm" + "time" +) + +const maxSize = 100 + +type CatalogDAL interface { + Select(ctx context.Context, eventID int) (*model.Event, error) + SelectList(ctx context.Context, page int, size int) ([]model.Event, int, error) + Save(ctx context.Context, record *model.Event) error + SelectOperations(ctx context.Context, serviceName string, operationID string) ([]*model.EventCatalog, error) +} + +func NewCatalogDAL() CatalogDAL { + var w catalogDALImpl + return &w +} + +type catalogDALImpl struct { +} + +func (c *catalogDALImpl) Select(ctx context.Context, eventID int) (*model.Event, error) { + var condition = model.Event{ID: eventID} + var r model.Event + if err := catalogDB.WithContext(ctx).Where(&condition).First(&r).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, err + } + return &r, nil +} + +func (c *catalogDALImpl) SelectList(ctx context.Context, page int, size int) ([]model.Event, int, error) { + var r []model.Event + db := catalogDB.WithContext(ctx).Where("1=1") + db = db.Where("status = ?", constants.NormalStatus) + if size > maxSize { + size = maxSize + } + if page == 0 { + page = 1 + } + var count int64 + db = db.Limit(size).Offset(size * (page - 1)).Order("update_time DESC") + if err := db.Find(&r).Limit(-1).Offset(-1).Count(&count).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, 0, nil + } + return nil, 0, err + } + return r, int(count), nil + +} + +func (c *catalogDALImpl) SelectOperations(ctx context.Context, serviceName string, + operationID string) ([]*model.EventCatalog, error) { + var res []*model.EventCatalog + var condition = model.EventCatalog{ServiceName: serviceName, OperationID: operationID} + if err := catalogDB.WithContext(ctx).Where(&condition).Find(&res).Error; err != nil { + return nil, err + } + return res, nil +} + +func (c *catalogDALImpl) Save(ctx context.Context, record *model.Event) error { + return catalogDB.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + if record.ID > 0 { + if err := c.delete(tx, record); err != nil { + return err + } + } + return c.create(tx, record) + }) +} + +func (c *catalogDALImpl) insert(tx *gorm.DB, record *model.EventCatalog) error { + return tx.Create(record).Error +} + +func (c *catalogDALImpl) insertEvent(tx *gorm.DB, record *model.Event) error { + return tx.Create(record).Error +} + +func (c *catalogDALImpl) delete(tx *gorm.DB, record *model.Event) error { + var handlers []func() error + handlers = append(handlers, func() error { + cond := model.Event{Status: constants.InvalidStatus, UpdateTime: time.Now()} + return tx.Where("id = ?", record.ID).Updates(&cond).Error + }, func() error { + cond := model.EventCatalog{Status: constants.InvalidStatus, UpdateTime: time.Now()} + return tx.Where("service_name = ?", record.Title).Updates(&cond).Error + }) + return util.GoAndWait(handlers...) +} + +func (c *catalogDALImpl) create(tx *gorm.DB, record *model.Event) error { + if len(record.Definition) == 0 { + return nil + } + var doc = new(v2.Document) + if err := v2.Decode(gconv.Bytes(record.Definition), &doc); err != nil { + return err + } + if len(doc.Channels()) == 0 { + return nil + } + var handlers []func() error + handlers = append(handlers, func() error { + return c.insertEvent(tx, c.buildEvent(record.Definition, doc)) + }) + for _, channel := range doc.Channels() { + for _, operation := range channel.Operations() { + var eventCatalog = c.buildEventCatalog(doc.Info().Title(), channel, operation) + handlers = append(handlers, func() error { + return c.insert(tx, eventCatalog) + }) + } + } + return util.GoAndWait(handlers...) +} + +func (c *catalogDALImpl) buildEventCatalog(serviceName string, channel asyncapi.Channel, + operation asyncapi.Operation) *model.EventCatalog { + var record model.EventCatalog + record.ServiceName = serviceName + record.OperationID = fmt.Sprintf("file://%s.yaml#%s", serviceName, operation.ID()) + record.ChannelName = channel.ID() + record.Type = string(operation.Type()) + record.Status = constants.NormalStatus + record.CreateTime = time.Now() + record.UpdateTime = time.Now() + record.Schema = gconv.String(operation.Messages()[0].Payload()) + return &record +} + +func (c *catalogDALImpl) buildEvent(definition string, doc asyncapi.Document) *model.Event { + var record model.Event + record.Title = doc.Info().Title() + record.FileName = fmt.Sprintf("%s.yaml", record.Title) + record.Definition = definition + record.Status = constants.NormalStatus + record.Version = doc.Info().Version() + record.CreateTime = time.Now() + record.UpdateTime = time.Now() + return &record +} diff --git a/eventmesh-catalog-go/internal/dal/config.go b/eventmesh-catalog-go/internal/dal/config.go new file mode 100644 index 0000000000..f09971a000 --- /dev/null +++ b/eventmesh-catalog-go/internal/dal/config.go @@ -0,0 +1,44 @@ +// 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. + +package dal + +import ( + "database/sql" + "gorm.io/gorm/logger" + "time" + + "gorm.io/driver/mysql" + "gorm.io/gorm" + + pmysql "github.com/apache/incubator-eventmesh/eventmesh-server-go/plugin/database/mysql" +) + +var catalogDB *gorm.DB + +func Open() error { + var err error + d, err := sql.Open("mysql", pmysql.PluginConfig.DSN) + d.SetMaxOpenConns(pmysql.PluginConfig.MaxOpen) + d.SetMaxIdleConns(pmysql.PluginConfig.MaxIdle) + d.SetConnMaxLifetime(time.Millisecond * time.Duration(pmysql.PluginConfig.MaxLifetime)) + + catalogDB, err = gorm.Open(mysql.New(mysql.Config{Conn: d}), + &gorm.Config{Logger: logger.Default.LogMode(logger.Silent)}) + if err != nil { + return err + } + return nil +} diff --git a/eventmesh-catalog-go/internal/dal/model/event.go b/eventmesh-catalog-go/internal/dal/model/event.go new file mode 100644 index 0000000000..5d6c3fc41a --- /dev/null +++ b/eventmesh-catalog-go/internal/dal/model/event.go @@ -0,0 +1,35 @@ +// 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. + +package model + +import ( + "time" +) + +type Event struct { + ID int `json:"id" gorm:"column:id;type:int;primaryKey;autoIncrement"` + Title string `json:"title" gorm:"column:title;type:varchar;size:1024"` + FileName string `json:"file_name" gorm:"column:file_name;type:varchar;size:1024"` + Definition string `json:"definition" gorm:"column:definition;type:text;"` + Status int `json:"status" gorm:"column:status;type:int"` + Version string `json:"version" gorm:"column:version;type:varchar;size:64"` + CreateTime time.Time `json:"create_time"` + UpdateTime time.Time `json:"update_time"` +} + +func (w Event) TableName() string { + return "t_event" +} diff --git a/eventmesh-catalog-go/internal/dal/model/event_catalog.go b/eventmesh-catalog-go/internal/dal/model/event_catalog.go new file mode 100644 index 0000000000..450b317208 --- /dev/null +++ b/eventmesh-catalog-go/internal/dal/model/event_catalog.go @@ -0,0 +1,36 @@ +// 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. + +package model + +import ( + "time" +) + +type EventCatalog struct { + ID int `json:"id" gorm:"column:id;type:int;primaryKey;autoIncrement"` + ServiceName string `json:"service_name" gorm:"column:service_name;type:varchar;size:256"` + OperationID string `json:"operation_id" gorm:"column:operation_id;type:varchar;size:1024"` + ChannelName string `json:"channel_name" gorm:"column:channel_name;type:varchar;size:1024"` + Type string `json:"type" gorm:"column:type;type:string"` + Schema string `json:"schema" gorm:"column:schema;type:text;"` + Status int `json:"status" gorm:"column:status;type:int"` + CreateTime time.Time `json:"create_time"` + UpdateTime time.Time `json:"update_time"` +} + +func (w EventCatalog) TableName() string { + return "t_event_catalog" +} diff --git a/eventmesh-catalog-go/internal/util/catalog_util.go b/eventmesh-catalog-go/internal/util/catalog_util.go new file mode 100644 index 0000000000..98f063e798 --- /dev/null +++ b/eventmesh-catalog-go/internal/util/catalog_util.go @@ -0,0 +1,60 @@ +// 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. + +package util + +import ( + "runtime" + "sync" + + "github.com/apache/incubator-eventmesh/eventmesh-server-go/log" +) + +// PanicBufLen is len of buffer used for stack trace logging +// when the goroutine panics, 1024 by default. +var PanicBufLen = 1024 + +// GoAndWait provides safe concurrent handling. Per input handler, it starts a goroutine. +// Then it waits until all handlers are done and will recover if any handler panics. +// The returned error is the first non-nil error returned by one of the handlers. +// It can be set that non-nil error will be returned if the "key" handler fails while other handlers always +// return nil error. +func GoAndWait(handlers ...func() error) error { + var ( + wg sync.WaitGroup + once sync.Once + err error + ) + for _, f := range handlers { + wg.Add(1) + go func(handler func() error) { + defer func() { + if e := recover(); e != nil { + buf := make([]byte, PanicBufLen) + buf = buf[:runtime.Stack(buf, false)] + log.Errorf("[PANIC]%v\n%s\n", e, buf) + } + wg.Done() + }() + if e := handler(); e != nil { + once.Do(func() { + err = e + }) + } + }(f) + } + wg.Wait() + return err +} diff --git a/eventmesh-catalog-go/internal/util/file_utils.go b/eventmesh-catalog-go/internal/util/file_utils.go new file mode 100644 index 0000000000..9dff3c8bab --- /dev/null +++ b/eventmesh-catalog-go/internal/util/file_utils.go @@ -0,0 +1,27 @@ +// 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. + +package util + +import "os" + +// Exists check if the file exists +func Exists(path string) bool { + _, err := os.Stat(path) + if err == nil { + return true + } + return os.IsExist(err) +} diff --git a/eventmesh-catalog-go/main.go b/eventmesh-catalog-go/main.go new file mode 100644 index 0000000000..969d03540c --- /dev/null +++ b/eventmesh-catalog-go/main.go @@ -0,0 +1,40 @@ +// 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. + +package main + +import ( + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/api" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/api/proto" + "github.com/apache/incubator-eventmesh/eventmesh-server-go/log" + _ "github.com/apache/incubator-eventmesh/eventmesh-server-go/pkg/naming/registry" + _ "github.com/apache/incubator-eventmesh/eventmesh-server-go/plugin/database/mysql" + _ "github.com/apache/incubator-eventmesh/eventmesh-server-go/plugin/naming/nacos/selector" +) + +func main() { + s, err := NewServer() + if err != nil { + log.Fatal("flow new server fail: " + err.Error()) + } + router(s) + if err = s.Run(); err != nil { + log.Fatal("run server fail: " + err.Error()) + } +} + +func router(s *Server) { + proto.RegisterCatalogServer(s.Server, api.NewCatalogImpl()) +} diff --git a/eventmesh-catalog-go/pkg/asyncapi/decode.go b/eventmesh-catalog-go/pkg/asyncapi/decode.go new file mode 100644 index 0000000000..378b7a5db3 --- /dev/null +++ b/eventmesh-catalog-go/pkg/asyncapi/decode.go @@ -0,0 +1,29 @@ +// 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. + +package asyncapi + +// Decoder decodes an AsyncAPI document (several formats can be supported). +// See https://github.com/asyncapi/parser-go#overview for the minimum supported schemas. +type Decoder interface { + Decode([]byte, interface{}) error +} + +// DecodeFunc is a helper func that implements the Decoder interface. +type DecodeFunc func([]byte, interface{}) error + +func (d DecodeFunc) Decode(b []byte, dst interface{}) error { + return d(b, dst) +} diff --git a/eventmesh-catalog-go/pkg/asyncapi/document.go b/eventmesh-catalog-go/pkg/asyncapi/document.go new file mode 100644 index 0000000000..ead3ce3302 --- /dev/null +++ b/eventmesh-catalog-go/pkg/asyncapi/document.go @@ -0,0 +1,212 @@ +// 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. + +package asyncapi + +// Document is an object representing an AsyncAPI document. +// NOTE: this interface is not completed yet. +type Document interface { + Extendable + Channels() []Channel + HasChannels() bool + ApplicationPublishableChannels() []Channel + ApplicationPublishableMessages() []Message + ApplicationPublishOperations() []Operation + ApplicationSubscribableChannels() []Channel + ApplicationSubscribableMessages() []Message + ApplicationSubscribeOperations() []Operation + ClientPublishableChannels() []Channel + ClientPublishableMessages() []Message + ClientPublishOperations() []Operation + ClientSubscribableChannels() []Channel + ClientSubscribableMessages() []Message + ClientSubscribeOperations() []Operation + Messages() []Message + Server(name string) (Server, bool) + Servers() []Server + HasServers() bool + Info() Info +} + +type Info interface { + Title() string + Version() string +} + +// Channel is an addressable component, made available by the server, for the organization of messages. +// Producer applications send messages to channels and consumer applications consume messages from channels. +type Channel interface { + Extendable + Identifiable + Describable + Path() string // Path is the identifier + Parameters() []ChannelParameter + HasParameters() bool + Operations() []Operation + Messages() []Message +} + +// ChannelParameter describes a parameter included in a channel name. +type ChannelParameter interface { + Extendable + Identifiable + Describable + Name() string + Schema() Schema +} + +// OperationType is the type of an operation. +type OperationType string + +// Operation describes a publish or a subscribe operation. +// This provides a place to document how and why messages are sent and received. +type Operation interface { + Extendable + Describable + ID() string + IsApplicationPublishing() bool + IsApplicationSubscribing() bool + IsClientPublishing() bool + IsClientSubscribing() bool + Messages() []Message + Summary() string + HasSummary() bool + Type() OperationType +} + +// Message describes a message received on a given channel and operation. +type Message interface { + Extendable + Describable + UID() string + Name() string + Title() string + HasTitle() bool + Summary() string + HasSummary() bool + ContentType() string + Payload() Schema +} + +// FalsifiableSchema is a variadic type used for some Schema fields. +// For example, additionalProperties value can be either `false` or a Schema. +type FalsifiableSchema interface { + IsFalse() bool + IsSchema() bool + Schema() Schema +} + +// Schema is an object that allows the definition of input and output data types. +// These types can be objects, but also primitives and arrays. +// This object is a superset of the JSON Schema Specification Draft 07. +type Schema interface { + Extendable + ID() string + AdditionalItems() FalsifiableSchema + AdditionalProperties() FalsifiableSchema + AllOf() []Schema + AnyOf() []Schema + CircularProps() []string + Const() interface{} + Contains() Schema + ContentEncoding() string + ContentMediaType() string + Default() interface{} + Definitions() map[string]Schema + Dependencies() map[string]Schema + Deprecated() bool + Description() string + Discriminator() string + Else() Schema + Enum() []interface{} + Examples() []interface{} + ExclusiveMaximum() *float64 + ExclusiveMinimum() *float64 + Format() string + HasCircularProps() bool + If() Schema + IsCircular() bool + Items() []Schema + Maximum() *float64 + MaxItems() *float64 + MaxLength() *float64 + MaxProperties() *float64 + Minimum() *float64 + MinItems() *float64 + MinLength() *float64 + MinProperties() *float64 + MultipleOf() *float64 + Not() Schema + OneOf() []Schema + Pattern() string + PatternProperties() map[string]Schema + Properties() map[string]Schema + Property(name string) Schema + PropertyNames() Schema + ReadOnly() bool + Required() []string + Then() Schema + Title() string + Type() []string + UID() string + UniqueItems() bool + WriteOnly() bool +} + +// Server is an object representing a message broker, a server or any other kind of computer program capable of +// sending and/or receiving data. +type Server interface { + Extendable + Identifiable + Describable + Name() string + HasName() bool + URL() string + HasURL() bool + Protocol() string + HasProtocol() bool + Variables() []ServerVariable +} + +// ServerVariable is an object representing a Server Variable for server URL template substitution. +type ServerVariable interface { + Extendable + Identifiable + Name() string + HasName() bool + DefaultValue() string + AllowedValues() []string // Parser API spec says any[], but AsyncAPI mentions is []string +} + +// Extendable means the object can have extensions. +// The extensions properties are implemented as patterned fields that are always prefixed by "x-". +// See https://www.asyncapi.com/docs/specifications/v2.0.0#specificationExtensions. +type Extendable interface { + HasExtension(name string) bool + Extension(name string) interface{} +} + +// Describable means the object can have a description. +type Describable interface { + Description() string + HasDescription() bool +} + +// Identifiable identifies objects. Some objects can have fields that identify themselves as unique resources. +// For example: `id` and `name` fields. +type Identifiable interface { + IDField() string + ID() string +} diff --git a/eventmesh-catalog-go/pkg/asyncapi/v2/decode.go b/eventmesh-catalog-go/pkg/asyncapi/v2/decode.go new file mode 100644 index 0000000000..ea9bca48bc --- /dev/null +++ b/eventmesh-catalog-go/pkg/asyncapi/v2/decode.go @@ -0,0 +1,114 @@ +// 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. + +package v2 + +import ( + "bytes" + "encoding/json" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/pkg/asyncapi" + "reflect" + + "github.com/asyncapi/parser-go/pkg/parser" + "github.com/mitchellh/mapstructure" + "github.com/pkg/errors" +) + +// Decode implements the Decoder interface. Decodes AsyncAPI V2.x.x documents. +func Decode(b []byte, dst interface{}) error { + r, err := parser.NewReader(string(b)) // parser should provide another method for parsing []byte + if err != nil { + return errors.Wrap(err, "error reading AsyncAPI doc") + } + + p, err := parser.New() + if err != nil { + return err + } + + w := bytes.NewBuffer(nil) + if err := p(r, w); err != nil { + return errors.Wrap(err, "error parsing AsyncAPI doc") + } + + raw := make(map[string]interface{}) + if err := json.Unmarshal(w.Bytes(), &raw); err != nil { + return err + } + + dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + DecodeHook: mapstructure.ComposeDecodeHookFunc(setModelIdentifierHook, setDefaultsHook), + Squash: true, + Result: dst, + }) + if err != nil { + return err + } + + return dec.Decode(raw) +} + +// setModelIdentifierHook is a hook for the mapstructure decoder. +// It checks if the destination type is a map of Identifiable elements and sets the proper identifier (name, id, etc) to it. +// Example: Useful for storing the name of the server in the Server struct (AsyncAPI doc does not have such field because it assumes the name is the key of the map). +func setModelIdentifierHook(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) { + if from.Kind() != reflect.Map || to.Kind() != reflect.Map { + return data, nil + } + + identifiableInterface := reflect.TypeOf((*asyncapi.Identifiable)(nil)).Elem() + if to.Key() != reflect.TypeOf("string") || !to.Elem().Implements(identifiableInterface) { + return data, nil + } + + fieldName := reflect.New(to.Elem()).Interface().(asyncapi.Identifiable).IDField() + for k, v := range data.(map[string]interface{}) { + // setting the value directly in the raw map. The struct needs to keep the mapstructure field tag so it unmarshals the field. + v.(map[string]interface{})[fieldName] = k + } + + return data, nil +} + +// MapStructureDefaultsProvider tells to mapstructure setDefaultsHook the defaults value for that type. +type MapStructureDefaultsProvider interface { + MapStructureDefaults() map[string]interface{} +} + +// setDefaultsHook is a hook for the mapstructure decoder. +// It checks if the destination type implements MapStructureDefaultsProvider. +// If so, it gets the defaults values from it and sets them if empty. +func setDefaultsHook(_ reflect.Type, to reflect.Type, data interface{}) (interface{}, error) { + if !to.Implements(reflect.TypeOf((*MapStructureDefaultsProvider)(nil)).Elem()) { + return data, nil + } + + var toType reflect.Type + switch to.Kind() { //nolint:exhaustive + case reflect.Array, reflect.Chan, reflect.Map, reflect.Ptr, reflect.Slice: + toType = to.Elem() + default: + toType = to + } + + defaults := reflect.New(toType).Interface().(MapStructureDefaultsProvider).MapStructureDefaults() + for k, v := range defaults { + if _, ok := data.(map[string]interface{})[k]; !ok { + data.(map[string]interface{})[k] = v + } + } + + return data, nil +} diff --git a/eventmesh-catalog-go/pkg/asyncapi/v2/v2.go b/eventmesh-catalog-go/pkg/asyncapi/v2/v2.go new file mode 100644 index 0000000000..90649d5e5c --- /dev/null +++ b/eventmesh-catalog-go/pkg/asyncapi/v2/v2.go @@ -0,0 +1,887 @@ +// 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. + +package v2 + +import ( + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/pkg/asyncapi" +) + +// Constants for Operation Types. +const ( + OperationTypePublish asyncapi.OperationType = "publish" + OperationTypeSubscribe asyncapi.OperationType = "subscribe" +) + +type Info struct { + TitleField string `mapstructure:"title" json:"title"` + VersionField string `mapstructure:"version" json:"version"` +} + +func (info *Info) Title() string { + return info.TitleField +} + +func (info *Info) Version() string { + return info.VersionField +} + +type Document struct { + Extendable + InfoField Info `mapstructure:"info" json:"info"` + ServersField map[string]Server `mapstructure:"servers" json:"servers"` + ChannelsField map[string]Channel `mapstructure:"channels" json:"channels"` +} + +func (d Document) Info() asyncapi.Info { + return &d.InfoField +} + +func (d Document) ApplicationPublishableChannels() []asyncapi.Channel { + return d.filterChannels(func(operation asyncapi.Operation) bool { + return operation.IsApplicationPublishing() + }) +} + +func (d Document) ApplicationPublishableMessages() []asyncapi.Message { + return d.filterMessages(func(operation asyncapi.Operation) bool { + return operation.IsApplicationPublishing() + }) +} + +func (d Document) ApplicationPublishOperations() []asyncapi.Operation { + return d.filterOperations(func(operation asyncapi.Operation) bool { + return operation.IsApplicationPublishing() + }) +} + +func (d Document) ApplicationSubscribableChannels() []asyncapi.Channel { + return d.filterChannels(func(operation asyncapi.Operation) bool { + return operation.IsApplicationSubscribing() + }) +} + +func (d Document) ApplicationSubscribableMessages() []asyncapi.Message { + return d.filterMessages(func(operation asyncapi.Operation) bool { + return operation.IsApplicationSubscribing() + }) +} + +func (d Document) ApplicationSubscribeOperations() []asyncapi.Operation { + return d.filterOperations(func(operation asyncapi.Operation) bool { + return operation.IsApplicationSubscribing() + }) +} + +func (d Document) Channels() []asyncapi.Channel { + var channels []asyncapi.Channel + for _, c := range d.ChannelsField { + channels = append(channels, c) + } + + return channels +} + +func (d Document) HasChannels() bool { + return len(d.ChannelsField) > 0 +} + +func (d Document) ClientPublishableChannels() []asyncapi.Channel { + return d.filterChannels(func(operation asyncapi.Operation) bool { + return operation.IsClientPublishing() + }) +} + +func (d Document) ClientPublishableMessages() []asyncapi.Message { + return d.filterMessages(func(operation asyncapi.Operation) bool { + return operation.IsClientPublishing() + }) +} + +func (d Document) ClientPublishOperations() []asyncapi.Operation { + return d.filterOperations(func(operation asyncapi.Operation) bool { + return operation.IsClientPublishing() + }) +} + +func (d Document) ClientSubscribableChannels() []asyncapi.Channel { + return d.filterChannels(func(operation asyncapi.Operation) bool { + return operation.IsClientSubscribing() + }) +} + +func (d Document) ClientSubscribableMessages() []asyncapi.Message { + return d.filterMessages(func(operation asyncapi.Operation) bool { + return operation.IsClientSubscribing() + }) +} + +func (d Document) ClientSubscribeOperations() []asyncapi.Operation { + return d.filterOperations(func(operation asyncapi.Operation) bool { + return operation.IsClientSubscribing() + }) +} + +func (d Document) Messages() []asyncapi.Message { + var messages []asyncapi.Message + for _, c := range d.Channels() { + messages = append(messages, c.Messages()...) + } + + return messages +} + +func (d Document) Server(name string) (asyncapi.Server, bool) { + s, ok := d.ServersField[name] + return s, ok +} + +func (d Document) Servers() []asyncapi.Server { + var servers []asyncapi.Server + for _, s := range d.ServersField { + servers = append(servers, s) + } + + return servers +} + +func (d Document) HasServers() bool { + return len(d.ServersField) > 0 +} + +func (d Document) filterChannels(filter func(operation asyncapi.Operation) bool) []asyncapi.Channel { + var channels []asyncapi.Channel + for _, c := range d.Channels() { + for _, o := range c.Operations() { + if filter(o) { + channels = append(channels, c) + } + } + } + + return channels +} + +func (d Document) filterMessages(filter func(operation asyncapi.Operation) bool) []asyncapi.Message { + var messages []asyncapi.Message + for _, c := range d.Channels() { + for _, o := range c.Operations() { + if filter(o) { + messages = append(messages, o.Messages()...) + } + } + } + + return messages +} + +func (d Document) filterOperations(filter func(operation asyncapi.Operation) bool) []asyncapi.Operation { + var operations []asyncapi.Operation + for _, c := range d.Channels() { + for _, o := range c.Operations() { + if filter(o) { + operations = append(operations, o) + } + } + } + + return operations +} + +// NewChannel creates a new Channel. Useful for testing. +func NewChannel(path string) *Channel { + return &Channel{ + PathField: path, + } +} + +type Channel struct { + Extendable + Describable `mapstructure:",squash"` + PathField string `mapstructure:"path" json:"path"` + ParametersField map[string]ChannelParameter `mapstructure:"parameters" json:"parameters"` + Subscribe *SubscribeOperation `mapstructure:"subscribe" json:"subscribe"` + Publish *PublishOperation `mapstructure:"publish" json:"publish"` +} + +func (c Channel) IDField() string { + return "path" +} + +func (c Channel) ID() string { + return c.PathField +} + +func (c Channel) Path() string { + return c.PathField +} + +func (c Channel) Parameters() []asyncapi.ChannelParameter { + var parameters []asyncapi.ChannelParameter + for _, p := range c.ParametersField { + parameters = append(parameters, p) + } + + return parameters +} + +func (c Channel) HasParameters() bool { + return len(c.ParametersField) > 0 +} + +func (c Channel) Operations() []asyncapi.Operation { + var operations []asyncapi.Operation + if c.Publish != nil { + operations = append(operations, c.Publish) + } + if c.Subscribe != nil { + operations = append(operations, c.Subscribe) + } + + return operations +} + +func (c Channel) Messages() []asyncapi.Message { + var messages []asyncapi.Message + for _, o := range c.Operations() { + messages = append(messages, o.Messages()...) + } + + return messages +} + +type ChannelParameter struct { + Extendable + Describable + NameField string `mapstructure:"name"` + SchemaField *Schema `mapstructure:"schema"` +} + +func (c ChannelParameter) IDField() string { + return "name" +} + +func (c ChannelParameter) ID() string { + return c.NameField +} + +func (c ChannelParameter) Name() string { + return c.NameField +} + +func (c ChannelParameter) Schema() asyncapi.Schema { + return c.SchemaField +} + +type SubscribeOperation struct { + Operation +} + +// NewSubscribeOperation creates a new SubscribeOperation. Useful for testing. +func NewSubscribeOperation(msgs ...*Message) *SubscribeOperation { + return &SubscribeOperation{Operation: *NewOperation(OperationTypeSubscribe, msgs...)} +} + +func (o SubscribeOperation) MapStructureDefaults() map[string]interface{} { + return map[string]interface{}{ + "operationType": OperationTypeSubscribe, + } +} + +// NewPublishOperation creates a new PublishOperation. Useful for testing. +func NewPublishOperation(msgs ...*Message) *PublishOperation { + return &PublishOperation{Operation: *NewOperation(OperationTypePublish, msgs...)} +} + +type PublishOperation struct { + Operation +} + +func (o PublishOperation) MapStructureDefaults() map[string]interface{} { + return map[string]interface{}{ + "operationType": OperationTypePublish, + } +} + +// NewOperation creates a new Operation. Useful for testing. +func NewOperation(operationType asyncapi.OperationType, msgs ...*Message) *Operation { + op := &Operation{ + OperationType: operationType, + } + + if len(msgs) == 0 { + return op + } + + op.MessageField = *NewMessages(msgs) + + return op +} + +type Operation struct { + Extendable + Describable `mapstructure:",squash"` + OperationIDField string `mapstructure:"operationId" json:"operationId"` + MessageField Messages `mapstructure:"message" json:"message"` + OperationType asyncapi.OperationType `mapstructure:"operationType" json:"operationType"` // set by hook + SummaryField string `mapstructure:"summary" json:"summary"` +} + +func (o Operation) ID() string { + return o.OperationIDField +} + +func (o Operation) IsApplicationPublishing() bool { + return o.Type() == OperationTypeSubscribe +} + +func (o Operation) IsApplicationSubscribing() bool { + return o.Type() == OperationTypePublish +} + +func (o Operation) IsClientPublishing() bool { + return o.Type() == OperationTypePublish +} + +func (o Operation) IsClientSubscribing() bool { + return o.Type() == OperationTypeSubscribe +} + +func (o Operation) Messages() []asyncapi.Message { + msgs := o.MessageField.Messages() + + convertedMsgs := make([]asyncapi.Message, len(msgs)) // Go lack of covariance :/ + for i, m := range msgs { + convertedMsgs[i] = m + } + return convertedMsgs +} + +func (o Operation) Type() asyncapi.OperationType { + return o.OperationType +} + +func (o Operation) Summary() string { + return o.SummaryField +} + +func (o Operation) HasSummary() bool { + return o.SummaryField != "" +} + +// Messages is a variadic type for Message object, which can be either one message or oneOf. +// See https://www.asyncapi.com/docs/specifications/v2.0.0#operationObject. +type Messages struct { + Message `mapstructure:",squash"` + OneOfField []*Message `mapstructure:"oneOf" json:"oneOf"` +} + +func (m *Messages) Messages() []*Message { + if len(m.OneOfField) > 0 { + return m.OneOfField + } + + return []*Message{&m.Message} +} + +// NewMessages creates Messages. +func NewMessages(msgs []*Message) *Messages { + if len(msgs) == 1 { + return &Messages{Message: *msgs[0]} + } + + return &Messages{OneOfField: msgs} +} + +type Message struct { + Extendable + Describable `mapstructure:",squash"` + NameField string `mapstructure:"name" json:"name"` + TitleField string `mapstructure:"title" json:"title"` + SummaryField string `mapstructure:"summary" json:"summary"` + ContentTypeField string `mapstructure:"contentType" json:"contentType"` + PayloadField *Schema `mapstructure:"payload" json:"payload"` +} + +func (m Message) UID() string { + return m.Name() +} + +func (m Message) Name() string { + return m.NameField +} + +func (m Message) Title() string { + return m.TitleField +} + +func (m Message) HasTitle() bool { + return m.TitleField != "" +} + +func (m Message) Summary() string { + return m.SummaryField +} + +func (m Message) HasSummary() bool { + return m.SummaryField != "" +} + +func (m Message) ContentType() string { + return m.ContentTypeField +} + +func (m Message) Payload() asyncapi.Schema { + return m.PayloadField +} + +type Schemas map[string]*Schema + +func (s Schemas) ToInterface(dst map[string]asyncapi.Schema) map[string]asyncapi.Schema { + if len(dst) > 0 { + return dst + } + + if dst == nil { + dst = make(map[string]asyncapi.Schema) + } + + for k, v := range s { + dst[k] = v + } + + return dst +} + +type FalsifiableSchema struct { + val interface{} +} + +// NewFalsifiableSchema creates a new FalsifiableSchema. +func NewFalsifiableSchema(val interface{}) *FalsifiableSchema { + if val == nil { + return nil + } + return &FalsifiableSchema{val: val} +} + +func (f FalsifiableSchema) IsFalse() bool { + _, ok := f.val.(bool) + return ok +} + +func (f FalsifiableSchema) IsSchema() bool { + _, ok := f.val.(*Schema) + return ok +} + +func (f FalsifiableSchema) Schema() asyncapi.Schema { + if f.IsSchema() { + return f.val.(*Schema) + } + + return nil +} + +type Schema struct { + Extendable + AdditionalItemsField interface{} `mapstructure:"additionalItems" json:"additionalItems,omitempty"` + AdditionalPropertiesField interface{} `mapstructure:"additionalProperties" json:"additionalProperties,omitempty"` // Schema || false + AllOfField []asyncapi.Schema `mapstructure:"allOf" json:"allOf,omitempty"` + AnyOfField []asyncapi.Schema `mapstructure:"anyOf" json:"anyOf,omitempty"` + ConstField interface{} `mapstructure:"const" json:"const,omitempty"` + ContainsField *Schema `mapstructure:"contains" json:"contains,omitempty"` + ContentEncodingField string `mapstructure:"contentEncoding" json:"contentEncoding,omitempty"` + ContentMediaTypeField string `mapstructure:"contentMediaType" json:"contentMediaType,omitempty"` + DefaultField interface{} `mapstructure:"default" json:"default,omitempty"` + DefinitionsField Schemas `mapstructure:"definitions" json:"definitions,omitempty"` + DependenciesField Schemas `mapstructure:"dependencies" json:"dependencies,omitempty"` + DeprecatedField bool `mapstructure:"deprecated" json:"deprecated,omitempty"` + DescriptionField string `mapstructure:"description" json:"description,omitempty"` + DiscriminatorField string `mapstructure:"discriminator" json:"discriminator,omitempty"` + ElseField *Schema `mapstructure:"else" json:"else,omitempty"` + EnumField []interface{} `mapstructure:"enum" json:"enum,omitempty"` + ExamplesField []interface{} `mapstructure:"examples" json:"examples,omitempty"` + ExclusiveMaximumField *float64 `mapstructure:"exclusiveMaximum" json:"exclusiveMaximum,omitempty"` + ExclusiveMinimumField *float64 `mapstructure:"exclusiveMinimum" json:"exclusiveMinimum,omitempty"` + FormatField string `mapstructure:"format" json:"format,omitempty"` + IDField string `mapstructure:"$id" json:"$id,omitempty"` + IfField *Schema `mapstructure:"if" json:"if,omitempty"` + ItemsField []asyncapi.Schema `mapstructure:"items" json:"items,omitempty"` + MaximumField *float64 `mapstructure:"maximum" json:"maximum,omitempty"` + MaxItemsField *float64 `mapstructure:"maxItems" json:"maxItems,omitempty"` + MaxLengthField *float64 `mapstructure:"maxLength" json:"maxLength,omitempty"` + MaxPropertiesField *float64 `mapstructure:"maxProperties" json:"maxProperties,omitempty"` + MinimumField *float64 `mapstructure:"minimum" json:"minimum,omitempty"` + MinItemsField *float64 `mapstructure:"minItems" json:"minItems,omitempty"` + MinLengthField *float64 `mapstructure:"minLength" json:"minLength,omitempty"` + MinPropertiesField *float64 `mapstructure:"minProperties" json:"minProperties,omitempty"` + MultipleOfField *float64 `mapstructure:"multipleOf" json:"multipleOf,omitempty"` + NotField *Schema `mapstructure:"not" json:"not,omitempty"` + OneOfField []asyncapi.Schema `mapstructure:"oneOf" json:"oneOf,omitempty"` + PatternField string `mapstructure:"pattern" json:"pattern,omitempty"` + PatternPropertiesField Schemas `mapstructure:"patternProperties" json:"patternProperties,omitempty"` + PropertiesField Schemas `mapstructure:"properties" json:"properties,omitempty"` + PropertyNamesField *Schema `mapstructure:"propertyNames" json:"propertyNames,omitempty"` + ReadOnlyField bool `mapstructure:"readOnly" json:"readOnly,omitempty"` + RequiredField []string `mapstructure:"required" json:"required,omitempty"` + ThenField *Schema `mapstructure:"then" json:"then,omitempty"` + TitleField string `mapstructure:"title" json:"title,omitempty"` + TypeField interface{} `mapstructure:"type" json:"type,omitempty"` // string | []string + UniqueItemsField bool `mapstructure:"uniqueItems" json:"uniqueItems,omitempty"` + WriteOnlyField bool `mapstructure:"writeOnly" json:"writeOnly,omitempty"` + + // cached converted map[string]asyncapi.Schema from map[string]*Schema + propertiesFieldMap map[string]asyncapi.Schema + patternPropertiesFieldMap map[string]asyncapi.Schema + definitionsFieldMap map[string]asyncapi.Schema + dependenciesFieldMap map[string]asyncapi.Schema +} + +func (s *Schema) AdditionalItems() asyncapi.FalsifiableSchema { + return NewFalsifiableSchema(s.AdditionalItemsField) +} + +func (s *Schema) AdditionalProperties() asyncapi.FalsifiableSchema { + return NewFalsifiableSchema(s.AdditionalPropertiesField) +} + +func (s *Schema) AllOf() []asyncapi.Schema { + return s.AllOfField +} + +func (s *Schema) AnyOf() []asyncapi.Schema { + return s.AnyOfField +} + +func (s *Schema) CircularProps() []string { + if props, ok := s.Extension("x-parser-circular-props").([]string); ok { + return props + } + + return nil +} + +func (s *Schema) Const() interface{} { + return s.ConstField +} + +func (s *Schema) Contains() asyncapi.Schema { + return s.ContainsField +} + +func (s *Schema) ContentEncoding() string { + return s.ContentEncodingField +} + +func (s *Schema) ContentMediaType() string { + return s.ContentMediaTypeField +} + +func (s *Schema) Default() interface{} { + return s.DefaultField +} + +func (s *Schema) Definitions() map[string]asyncapi.Schema { + s.definitionsFieldMap = s.DefinitionsField.ToInterface(s.definitionsFieldMap) + return s.definitionsFieldMap +} + +func (s *Schema) Dependencies() map[string]asyncapi.Schema { + s.dependenciesFieldMap = s.DependenciesField.ToInterface(s.dependenciesFieldMap) + return s.dependenciesFieldMap +} + +func (s *Schema) Deprecated() bool { + return s.DeprecatedField +} + +func (s *Schema) Description() string { + return s.DescriptionField +} + +func (s *Schema) Discriminator() string { + return s.DiscriminatorField +} + +func (s *Schema) Else() asyncapi.Schema { + return s.ElseField +} + +func (s *Schema) Enum() []interface{} { + return s.EnumField +} + +func (s *Schema) Examples() []interface{} { + return s.ExamplesField +} + +func (s *Schema) ExclusiveMaximum() *float64 { + return s.ExclusiveMaximumField +} + +func (s *Schema) ExclusiveMinimum() *float64 { + return s.ExclusiveMinimumField +} + +func (s *Schema) Format() string { + return s.FormatField +} + +func (s *Schema) HasCircularProps() bool { + return len(s.CircularProps()) > 0 +} + +func (s *Schema) ID() string { + return s.IDField +} + +func (s *Schema) If() asyncapi.Schema { + return s.IfField +} + +func (s *Schema) IsCircular() bool { + if isCircular, ok := s.Extension("x-parser-circular").(bool); ok { + return isCircular + } + + return false +} + +func (s *Schema) Items() []asyncapi.Schema { + return s.ItemsField +} + +func (s *Schema) Maximum() *float64 { + return s.MaximumField +} + +func (s *Schema) MaxItems() *float64 { + return s.MaxItemsField +} + +func (s *Schema) MaxLength() *float64 { + return s.MaxLengthField +} + +func (s *Schema) MaxProperties() *float64 { + return s.MaxPropertiesField +} + +func (s *Schema) Minimum() *float64 { + return s.MinimumField +} + +func (s *Schema) MinItems() *float64 { + return s.MinItemsField +} + +func (s *Schema) MinLength() *float64 { + return s.MinLengthField +} + +func (s *Schema) MinProperties() *float64 { + return s.MinPropertiesField +} + +func (s *Schema) MultipleOf() *float64 { + return s.MultipleOfField +} + +func (s *Schema) Not() asyncapi.Schema { + return s.NotField +} + +func (s *Schema) OneOf() []asyncapi.Schema { + return s.OneOfField +} + +func (s *Schema) Pattern() string { + return s.PatternField +} + +func (s *Schema) PatternProperties() map[string]asyncapi.Schema { + s.patternPropertiesFieldMap = s.PatternPropertiesField.ToInterface(s.patternPropertiesFieldMap) + return s.patternPropertiesFieldMap +} + +func (s *Schema) Properties() map[string]asyncapi.Schema { + s.propertiesFieldMap = s.PropertiesField.ToInterface(s.propertiesFieldMap) + return s.propertiesFieldMap +} + +func (s *Schema) Property(name string) asyncapi.Schema { + return s.PropertiesField[name] +} + +func (s *Schema) PropertyNames() asyncapi.Schema { + return s.PropertyNamesField +} + +func (s *Schema) ReadOnly() bool { + return s.ReadOnlyField +} + +func (s *Schema) Required() []string { + return s.RequiredField +} + +func (s *Schema) Then() asyncapi.Schema { + return s.ThenField +} + +func (s *Schema) Title() string { + return s.TitleField +} + +func (s *Schema) Type() []string { + if stringVal, isString := s.TypeField.(string); isString { + return []string{stringVal} + } + + if sliceVal, isSlice := s.TypeField.([]string); isSlice { + return sliceVal + } + + return nil +} + +func (s *Schema) UID() string { + if id := s.ID(); id != "" { + return id + } + + // This is not yet supported by parser-go + parserGeneratedID, ok := s.Extension("x-parser-id").(string) + if ok { + return parserGeneratedID + } + + return "" +} + +func (s *Schema) UniqueItems() bool { + return s.UniqueItemsField +} + +func (s *Schema) WriteOnly() bool { + return s.WriteOnlyField +} + +type Server struct { + Extendable + Describable `mapstructure:",squash"` + NameField string `mapstructure:"name" json:"name"` + ProtocolField string `mapstructure:"protocol" json:"protocol"` + URLField string `mapstructure:"url" json:"url"` + VariablesField map[string]ServerVariable `mapstructure:"variables" json:"variables"` +} + +func (s Server) Variables() []asyncapi.ServerVariable { + var vars []asyncapi.ServerVariable + for _, v := range s.VariablesField { + vars = append(vars, v) + } + + return vars +} + +func (s Server) IDField() string { + return "name" +} + +func (s Server) ID() string { + return s.NameField +} + +func (s Server) Name() string { + return s.NameField +} + +func (s Server) HasName() bool { + return s.NameField != "" +} + +func (s Server) URL() string { + return s.URLField +} + +func (s Server) HasURL() bool { + return s.URLField != "" +} + +func (s Server) Protocol() string { + return s.ProtocolField +} + +func (s Server) HasProtocol() bool { + return s.ProtocolField != "" +} + +type ServerVariable struct { + Extendable + NameField string `mapstructure:"name" json:"name"` + Default string `mapstructure:"default" json:"default"` + Enum []string `mapstructure:"enum" json:"enum"` +} + +func (s ServerVariable) IDField() string { + return "name" +} + +func (s ServerVariable) ID() string { + return s.NameField +} + +func (s ServerVariable) Name() string { + return s.NameField +} + +func (s ServerVariable) HasName() bool { + return s.NameField != "" +} + +func (s ServerVariable) DefaultValue() string { + return s.Default +} + +func (s ServerVariable) AllowedValues() []string { + return s.Enum +} + +type Describable struct { + DescriptionField string `mapstructure:"description" json:"description"` +} + +func (d Describable) Description() string { + return d.DescriptionField +} + +func (d Describable) HasDescription() bool { + return d.DescriptionField != "" +} + +type Extendable struct { + Raw map[string]interface{} `mapstructure:",remain" json:"-"` +} + +func (e Extendable) HasExtension(name string) bool { + _, ok := e.Raw[name] + return ok +} + +func (e Extendable) Extension(name string) interface{} { + return e.Raw[name] +} diff --git a/eventmesh-catalog-go/server.go b/eventmesh-catalog-go/server.go new file mode 100644 index 0000000000..d1ca75ebfa --- /dev/null +++ b/eventmesh-catalog-go/server.go @@ -0,0 +1,84 @@ +// 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. + +package main + +import ( + "errors" + "fmt" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/dal" + "github.com/apache/incubator-eventmesh/eventmesh-catalog-go/internal/util" + "github.com/apache/incubator-eventmesh/eventmesh-server-go/config" + "github.com/apache/incubator-eventmesh/eventmesh-server-go/pkg/naming/registry" + "google.golang.org/grpc" + "net" +) + +type Server struct { + Server *grpc.Server +} + +func NewServer() (*Server, error) { + var s Server + if err := s.SetupConfig(); err != nil { + return nil, err + } + if err := dal.Open(); err != nil { + return nil, err + } + + s.Server = grpc.NewServer() + return &s, nil +} + +func (s *Server) Run() error { + l, err := s.listen() + if err != nil { + return err + } + reg := registry.Get(config.GlobalConfig().Server.Name) + if reg == nil { + return errors.New("service name=" + config.GlobalConfig().Server.Name + " not find registry") + } + if err = reg.Register(config.GlobalConfig().Server.Name); err != nil { + return err + } + return s.Server.Serve(l) +} + +func (s *Server) SetupConfig() error { + config.ServerConfigPath = "./configs/catalog.yaml" + if !util.Exists(config.ServerConfigPath) { + config.ServerConfigPath = "../configs/catalog.yaml" + } + if !util.Exists(config.ServerConfigPath) { + config.ServerConfigPath = "../conf/catalog.yaml" + } + cfg, err := config.LoadConfig(config.ServerConfigPath) + if err != nil { + return err + } + config.SetGlobalConfig(cfg) + + return config.Setup(cfg) +} + +func (s *Server) listen() (net.Listener, error) { + listener, err := net.Listen("tcp", fmt.Sprintf(":%d", config.GlobalConfig().Server.Port)) + if err != nil { + return nil, err + } + return listener, nil +} diff --git a/eventmesh-common/build.gradle b/eventmesh-common/build.gradle new file mode 100644 index 0000000000..59fe1587d2 --- /dev/null +++ b/eventmesh-common/build.gradle @@ -0,0 +1,80 @@ +/* + * 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. + */ + +def grpcVersion = '1.42.2' + +dependencies { + api "com.google.guava:guava" + api "org.slf4j:slf4j-api" + api "org.assertj:assertj-core" + api "org.apache.commons:commons-collections4" + api "org.apache.commons:commons-text" + api "org.apache.commons:commons-lang3" + + implementation "org.apache.logging.log4j:log4j-api" + implementation "org.apache.logging.log4j:log4j-core" + implementation "org.apache.logging.log4j:log4j-slf4j-impl" + + implementation 'com.github.seancfoley:ipaddress' + + implementation "com.lmax:disruptor" + + api "com.fasterxml.jackson.core:jackson-databind" + api "com.fasterxml.jackson.core:jackson-core" + api "com.fasterxml.jackson.core:jackson-annotations" + + implementation "org.apache.httpcomponents:httpclient" + + implementation "io.netty:netty-all" + + implementation "io.grpc:grpc-protobuf:${grpcVersion}" + implementation "io.grpc:grpc-stub:${grpcVersion}" + implementation "javax.annotation:javax.annotation-api:1.3.2" + + implementation "com.github.stefanbirkner:system-rules" + + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + + testCompileOnly 'org.projectlombok:lombok' + testAnnotationProcessor 'org.projectlombok:lombok' + + testImplementation "org.apache.commons:commons-lang3" + + testImplementation "com.google.guava:guava" + + testImplementation "org.slf4j:slf4j-api" + testImplementation "org.apache.logging.log4j:log4j-api" + testImplementation "org.apache.logging.log4j:log4j-core" + testImplementation "org.apache.logging.log4j:log4j-slf4j-impl" + + testImplementation "com.lmax:disruptor" + + testImplementation "com.fasterxml.jackson.core:jackson-databind" + testImplementation "com.fasterxml.jackson.core:jackson-core" + testImplementation "com.fasterxml.jackson.core:jackson-annotations" + + testImplementation "org.apache.httpcomponents:httpclient" + + testImplementation "io.netty:netty-all" + + testImplementation "org.assertj:assertj-core" + + testImplementation "org.mockito:mockito-core" + testImplementation "org.powermock:powermock-module-junit4" + testImplementation "org.powermock:powermock-api-mockito2" +} diff --git a/eventmesh-common/gradle.properties b/eventmesh-common/gradle.properties new file mode 100644 index 0000000000..b1312a0905 --- /dev/null +++ b/eventmesh-common/gradle.properties @@ -0,0 +1,16 @@ +# +# 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. +# diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/Constants.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/Constants.java new file mode 100644 index 0000000000..29212ca1d3 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/Constants.java @@ -0,0 +1,171 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +public class Constants { + + public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + + public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; + + public static final String LANGUAGE_JAVA = "JAVA"; + + public static final String HTTP_PROTOCOL_PREFIX = "http://"; + + public static final String HTTPS_PROTOCOL_PREFIX = "https://"; + + public static final String PROTOCOL_TYPE = "protocoltype"; + + public static final String PROTOCOL_VERSION = "protocolversion"; + + public static final String PROTOCOL_DESC = "protocoldesc"; + + public static final int DEFAULT_HTTP_TIME_OUT = 15000; + + public static final String EVENTMESH_MESSAGE_CONST_TTL = "ttl"; + + public static final String DEFAULT_EVENTMESH_MESSAGE_TTL = "4000"; + + public static final Integer DEFAULT_CLIENT_UNACK = 12; + + public static final String CONSTANTS_SERVICE_DESC_ENV = "env"; + + public static final String CONSTANTS_SERVICE_DESC_VERSION = "version"; + + public static final String CONSTANTS_INSTANCE_DESC_ENV = "env"; + + public static final String CONSTANTS_INSTANCE_DESC_IDC = "idc"; + + public static final String CONSTANTS_INSTANCE_DESC_SYSID = "sysId"; + + public static final String CONSTANTS_INSTANCE_DESC_IP = "ip"; + + public static final String CONSTANTS_INSTANCE_DESC_PORT = "port"; + + public static final String KEY_CONSTANTS_INSTANCE_DESC_PID = "pid"; + + public static final String RMB_UNIQ_ID = "rmbuniqid"; + + public static final String IDC_SEPERATER = "-"; + + public static final String PROPERTY_MESSAGE_TIMEOUT = "timeout"; + + public static final String PROPERTY_MESSAGE_SEARCH_KEYS = "searchkeys"; + + public static final String PROPERTY_MESSAGE_QUEUE_ID = "queueid"; + + public static final String PROPERTY_MESSAGE_QUEUE_OFFSET = "queueoffset"; + + public static final String PROPERTY_MESSAGE_DESTINATION = "destination"; + + public static final String PROPERTY_MESSAGE_MESSAGE_ID = "messageid"; + + public static final String PROPERTY_MESSAGE_BORN_HOST = "bornhost"; + + public static final String PROPERTY_MESSAGE_BORN_TIMESTAMP = "borntimestamp"; + + public static final String PROPERTY_MESSAGE_STORE_HOST = "storehost"; + + public static final String PROPERTY_MESSAGE_STORE_TIMESTAMP = "storetimestamp"; + + public static final String MESSAGE_PROP_SEPARATOR = "99"; + + public static final String EVENTMESH_CONF_HOME = System.getProperty("confPath", System.getenv("confPath")); + + public static final String PRODUCER_ID = "PRODUCER_ID"; + + public static final String CONSUMER_ID = "CONSUMER_ID"; + + public static final String BROADCAST_PREFIX = "broadcast-"; + + public static final String IS_BROADCAST = "isBroadcast"; + + public static final String CONSUMER_GROUP = "consumerGroup"; + + public static final String PRODUCER_GROUP = "producerGroup"; + + public static final String INSTANCE_NAME = "instanceName"; + + public static final String ACCESS_POINTS = "ACCESS_POINTS"; + + public static final String REGION = "REGION"; + + public static final String MESSAGE_MODEL = "MESSAGE_MODEL"; + + public static final String NAMESPACE = "namespace"; + + public static final String RMQ_PRODUCER_GROUP = "RMQ_PRODUCER_GROUP"; + + public static final String OPERATION_TIMEOUT = "OPERATION_TIMEOUT"; + + public static String CLOUD_EVENTS_PROTOCOL_NAME = "cloudevents"; + + public static String EM_MESSAGE_PROTOCOL_NAME = "eventmeshmessage"; + + public static String OPEN_MESSAGE_PROTOCOL_NAME = "openmessage"; + + // delimiter define + public static final String COMMA = ","; + + public static final String VERTICAL_LINE = "|"; + + public static final String COLON = ":"; + + public static final String HYPHEN = "-"; + + public static final String DOT = "."; + + public static final String POUND = "#"; + + public static final String ASTERISK = "*"; + + public static final String UNDER_LINE = "_"; + + public static final String LEFT_PARENTHESIS = "("; + + public static final String RIGHT_PARENTHESIS = ")"; + + public static final String LINE_BREAK = "\n"; + + public static final String TAB = "\t"; + + public static final String AT = "@"; + + public static final String QUESTION_MARK = "?"; + + public static final String AND = "&"; + + public static final String EQ = "="; + + public static final String EMPTY = ""; + + public static final int SUCCESS_CODE = 200; + + /** + * GRPC PROTOCOL + */ + public static final String PROTOCOL_GRPC = "grpc"; + + /** + * application/cloudevents+json Content-type + */ + public static final String CONTENT_TYPE_CLOUDEVENTS_JSON = "application/cloudevents+json"; +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/EventMeshMessage.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/EventMeshMessage.java new file mode 100644 index 0000000000..8fecc700fe --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/EventMeshMessage.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common; + +import java.util.HashMap; +import java.util.Map; + +import lombok.Builder; +import lombok.Data; + +/** + * EventMesh message. + */ +@Builder +@Data +public class EventMeshMessage { + + private String bizSeqNo; + + private String uniqueId; + + private String topic; + + private String content; + + private Map prop; + + @Builder.Default + private final long createTime = System.currentTimeMillis(); + + public EventMeshMessage addProp(String key, String val) { + if (prop == null) { + prop = new HashMap<>(); + } + prop.put(key, val); + return this; + } + + public String getProp(String key) { + if (prop == null) { + return null; + } + return prop.get(key); + } + + public EventMeshMessage removePropIfPresent(String key) { + if (prop == null) { + + return this; + } + prop.remove(key); + return this; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/ThreadPoolFactory.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/ThreadPoolFactory.java new file mode 100644 index 0000000000..8b6e4379d2 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/ThreadPoolFactory.java @@ -0,0 +1,92 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +public class ThreadPoolFactory { + + public static ThreadPoolExecutor createThreadPoolExecutor(int core, int max, final String threadName) { + return createThreadPoolExecutor(core, max, threadName, true); + } + + public static ThreadPoolExecutor createThreadPoolExecutor(int core, int max, final String threadName, + final boolean isDaemon) { + return createThreadPoolExecutor(core, max, new LinkedBlockingQueue<>(1000), threadName, isDaemon); + } + + public static ThreadPoolExecutor createThreadPoolExecutor(int core, int max, BlockingQueue blockingQueue, + final String threadName, final boolean isDaemon) { + return new ThreadPoolExecutor(core, max, 10 * 1000, TimeUnit.MILLISECONDS, blockingQueue, + new ThreadFactoryBuilder().setNameFormat(threadName).setDaemon(isDaemon).build() + ); + } + + public static ThreadPoolExecutor createThreadPoolExecutor(int core, int max, ThreadFactory threadFactory) { + return createThreadPoolExecutor(core, max, new LinkedBlockingQueue<>(1000), threadFactory); + } + + public static ThreadPoolExecutor createThreadPoolExecutor(int core, int max, BlockingQueue blockingQueue, + ThreadFactory threadFactory) { + return new ThreadPoolExecutor(core, max, 10 * 1000, TimeUnit.MILLISECONDS, blockingQueue, threadFactory); + } + + public static ScheduledExecutorService createSingleScheduledExecutor(final String threadName) { + return Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { + private AtomicInteger ai = new AtomicInteger(0); + + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r, threadName + ai.incrementAndGet()); + thread.setDaemon(true); + return thread; + } + }); + } + + public static ScheduledExecutorService createScheduledExecutor(int core, final String threadName) { + return createScheduledExecutor(core, threadName, true); + } + + public static ScheduledExecutorService createScheduledExecutor(int core, final String threadName, + final boolean isDaemon) { + return Executors.newScheduledThreadPool(core, new ThreadFactory() { + private AtomicInteger ai = new AtomicInteger(0); + + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r, threadName + ai.incrementAndGet()); + thread.setDaemon(isDaemon); + return thread; + } + }); + } + + public static ScheduledExecutorService createScheduledExecutor(int core, ThreadFactory threadFactory) { + return Executors.newScheduledThreadPool(core, threadFactory); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/config/CommonConfiguration.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/config/CommonConfiguration.java new file mode 100644 index 0000000000..e0ed6960bb --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/config/CommonConfiguration.java @@ -0,0 +1,203 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.config; + +import org.apache.eventmesh.common.utils.AssertUtils; +import org.apache.eventmesh.common.utils.ConfigurationContextUtil; +import org.apache.eventmesh.common.utils.IPUtils; + +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import com.google.common.base.Preconditions; + +import lombok.Data; + +@Data +public class CommonConfiguration { + private transient String eventMeshEnv = "P"; + private transient String eventMeshIDC = "FT"; + private transient String eventMeshCluster = "LS"; + + private transient String eventMeshName = ""; + private transient List eventMeshProvideServerProtocols; + private transient String sysID = "5477"; + private transient String eventMeshConnectorPluginType = "rocketmq"; + private transient String eventMeshSecurityPluginType = "security"; + private transient String eventMeshRegistryPluginType = "namesrv"; + private transient List eventMeshMetricsPluginType; + private transient String eventMeshTracePluginType; + + private transient String namesrvAddr = ""; + private transient String eventMeshRegistryPluginUsername = ""; + private transient String eventMeshRegistryPluginPassword = ""; + private transient Integer eventMeshRegisterIntervalInMills = 10 * 1000; + private transient Integer eventMeshFetchRegistryAddrInterval = 10 * 1000; + private transient String eventMeshServerIp = null; + private transient boolean eventMeshServerSecurityEnable = false; + + private transient boolean eventMeshServerRegistryEnable = false; + + private transient boolean eventMeshServerTraceEnable = false; + + protected transient ConfigurationWrapper configurationWrapper; + + private transient String eventMeshWebhookOrigin = "eventmesh." + eventMeshIDC; + + public CommonConfiguration(ConfigurationWrapper configurationWrapper) { + this.configurationWrapper = configurationWrapper; + } + + public String getMeshGroup() { + return String.join("-", this.eventMeshEnv, this.eventMeshCluster, this.sysID); + } + + + public void init() { + + if (configurationWrapper != null) { + eventMeshEnv = checkNotEmpty(ConfKeys.KEYS_EVENTMESH_ENV); + + sysID = checkNumeric(ConfKeys.KEYS_EVENTMESH_SYSID); + + eventMeshCluster = checkNotEmpty(ConfKeys.KEYS_EVENTMESH_SERVER_CLUSTER); + + eventMeshName = checkNotEmpty(ConfKeys.KEYS_EVENTMESH_SERVER_NAME); + + eventMeshIDC = checkNotEmpty(ConfKeys.KEYS_EVENTMESH_IDC); + + eventMeshServerIp = get(ConfKeys.KEYS_EVENTMESH_SERVER_HOST_IP, IPUtils::getLocalAddress); + + eventMeshConnectorPluginType = checkNotEmpty(ConfKeys.KEYS_ENENTMESH_CONNECTOR_PLUGIN_TYPE); + + eventMeshServerSecurityEnable = Boolean.parseBoolean(get(ConfKeys.KEYS_EVENTMESH_SECURITY_ENABLED, () -> "false")); + + eventMeshSecurityPluginType = checkNotEmpty(ConfKeys.KEYS_ENENTMESH_SECURITY_PLUGIN_TYPE); + + eventMeshServerRegistryEnable = Boolean.parseBoolean(get(ConfKeys.KEYS_EVENTMESH_REGISTRY_ENABLED, () -> "false")); + + eventMeshRegistryPluginType = checkNotEmpty(ConfKeys.KEYS_ENENTMESH_REGISTRY_PLUGIN_TYPE); + + namesrvAddr = checkNotEmpty(ConfKeys.KEYS_EVENTMESH_REGISTRY_PULGIN_SERVER_ADDR); + + eventMeshRegistryPluginUsername = + configurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_REGISTRY_PULGIN_USERNAME, ""); + + eventMeshRegistryPluginPassword = + configurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_REGISTRY_PULGIN_PASSWORD, ""); + + String metricsPluginType = configurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_METRICS_PLUGIN_TYPE); + if (StringUtils.isNotEmpty(metricsPluginType)) { + eventMeshMetricsPluginType = Arrays + .stream(metricsPluginType.split(",")) + .filter(StringUtils::isNotBlank) + .map(String::trim) + .collect(Collectors.toList()); + } + + eventMeshProvideServerProtocols = getProvideServerProtocols(); + + eventMeshServerTraceEnable = Boolean.parseBoolean(get(ConfKeys.KEYS_EVENTMESH_TRACE_ENABLED, () -> "false")); + if (eventMeshServerTraceEnable) { + eventMeshTracePluginType = checkNotEmpty(ConfKeys.KEYS_EVENTMESH_TRACE_PLUGIN_TYPE); + } + } + } + + private String checkNotEmpty(String key) { + String value = configurationWrapper.getProp(key); + if (value != null) { + value = StringUtils.deleteWhitespace(value); + } + AssertUtils.notBlack(value, key + " is invalidated"); + return value; + } + + private String checkNumeric(String key) { + String value = configurationWrapper.getProp(key); + if (value != null) { + value = StringUtils.deleteWhitespace(value); + } + Preconditions.checkState(StringUtils.isNotEmpty(value) && StringUtils.isNumeric(value), key + " is invalidated"); + return value; + } + + private String get(String key, Supplier defaultValueSupplier) { + String value = configurationWrapper.getProp(key); + if (value != null) { + value = StringUtils.deleteWhitespace(value); + } + return StringUtils.isEmpty(value) ? defaultValueSupplier.get() : value; + } + + public List getProvideServerProtocols() { + String provideProtocols = configurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_SERVER_PROVIDE_PROTOCOLS); + if (StringUtils.isNotEmpty(provideProtocols)) { + return Arrays.stream(provideProtocols.split(",")).filter(StringUtils::isNotBlank).map(String::trim).collect(Collectors.toList()); + } else { + return Collections.singletonList(ConfigurationContextUtil.HTTP); + } + } + + static class ConfKeys { + public static final String KEYS_EVENTMESH_ENV = "eventMesh.server.env"; + + public static final String KEYS_EVENTMESH_IDC = "eventMesh.server.idc"; + + public static final String KEYS_EVENTMESH_SYSID = "eventMesh.sysid"; + + public static final String KEYS_EVENTMESH_SERVER_CLUSTER = "eventMesh.server.cluster"; + + public static final String KEYS_EVENTMESH_SERVER_NAME = "eventMesh.server.name"; + + public static final String KEYS_EVENTMESH_SERVER_PROVIDE_PROTOCOLS = "eventMesh.server.provide.protocols"; + + public static final String KEYS_EVENTMESH_SERVER_HOST_IP = "eventMesh.server.hostIp"; + + public static final String KEYS_EVENTMESH_SERVER_REGISTER_INTERVAL = "eventMesh.server.registry.registerIntervalInMills"; + + public static final String KEYS_EVENTMESH_SERVER_FETCH_REGISTRY_ADDR_INTERVAL = "eventMesh.server.registry.fetchRegistryAddrIntervalInMills"; + + public static final String KEYS_ENENTMESH_CONNECTOR_PLUGIN_TYPE = "eventMesh.connector.plugin.type"; + + public static final String KEYS_EVENTMESH_SECURITY_ENABLED = "eventMesh.server.security.enabled"; + + public static final String KEYS_ENENTMESH_SECURITY_PLUGIN_TYPE = "eventMesh.security.plugin.type"; + + public static final String KEYS_EVENTMESH_REGISTRY_ENABLED = "eventMesh.registry.plugin.enabled"; + + public static final String KEYS_ENENTMESH_REGISTRY_PLUGIN_TYPE = "eventMesh.registry.plugin.type"; + + public static final String KEYS_EVENTMESH_REGISTRY_PULGIN_SERVER_ADDR = "eventMesh.registry.plugin.server-addr"; + + public static final String KEYS_EVENTMESH_REGISTRY_PULGIN_USERNAME = "eventMesh.registry.plugin.username"; + + public static final String KEYS_EVENTMESH_REGISTRY_PULGIN_PASSWORD = "eventMesh.registry.plugin.password"; + + public static final String KEYS_EVENTMESH_METRICS_PLUGIN_TYPE = "eventMesh.metrics.plugin"; + + public static final String KEYS_EVENTMESH_TRACE_ENABLED = "eventMesh.server.trace.enabled"; + + public static final String KEYS_EVENTMESH_TRACE_PLUGIN_TYPE = "eventMesh.trace.plugin"; + } +} \ No newline at end of file diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/config/ConfigurationWrapper.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/config/ConfigurationWrapper.java new file mode 100644 index 0000000000..3df946709a --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/config/ConfigurationWrapper.java @@ -0,0 +1,183 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.config; + +import org.apache.eventmesh.common.file.FileChangeContext; +import org.apache.eventmesh.common.file.FileChangeListener; +import org.apache.eventmesh.common.file.WatchFileManager; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.Preconditions; + +public class ConfigurationWrapper { + + public static final Logger LOG = LoggerFactory.getLogger(ConfigurationWrapper.class); + + private final transient String directoryPath; + + private final transient String fileName; + + private final transient Properties properties = new Properties(); + + private final transient String file; + + private final transient boolean reload; + + + private final transient FileChangeListener fileChangeListener = new FileChangeListener() { + @Override + public void onChanged(FileChangeContext changeContext) { + load(); + } + + @Override + public boolean support(FileChangeContext changeContext) { + return changeContext.getWatchEvent().context().toString().contains(fileName); + } + }; + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public ConfigurationWrapper(String directoryPath, String fileName, boolean reload) { + Objects.requireNonNull(directoryPath, "please configure environment variable 'confPath'"); + Objects.requireNonNull(fileName, "please configure environment variable 'fileName'"); + + this.directoryPath = directoryPath + .replace('/', File.separator.charAt(0)) + .replace('\\', File.separator.charAt(0)); + this.fileName = fileName; + this.file = (directoryPath + File.separator + fileName) + .replace('/', File.separator.charAt(0)) + .replace('\\', File.separator.charAt(0)); + this.reload = reload; + init(); + } + + private void init() { + load(); + if (this.reload) { + WatchFileManager.registerFileChangeListener(directoryPath, fileChangeListener); + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + if (LOG.isInfoEnabled()) { + LOG.info("Configuration reload task closed"); + } + WatchFileManager.deregisterFileChangeListener(directoryPath); + })); + } + } + + private void load() { + Objects.requireNonNull(file, "properties can not be null"); + + try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), + StandardCharsets.UTF_8))) { + if (LOG.isInfoEnabled()) { + LOG.info("loading config: {}", file); + } + properties.load(reader); + } catch (IOException e) { + LOG.error("loading properties [{}] error", file, e); + } + } + + public String getProp(String key) { + return getProp(key, null); + } + + /** + * get key value if value is null then return defaultValue + * @param key key + * @param defaultValue defaultValue + * @return string + */ + public String getProp(String key, String defaultValue) { + return StringUtils.isEmpty(key) ? defaultValue : properties.getProperty(key, defaultValue); + } + + public int getIntProp(String configKey, int defaultValue) { + Objects.requireNonNull(configKey, "configKey can not be null"); + + String configValue = StringUtils.deleteWhitespace(getProp(configKey)); + if (StringUtils.isEmpty(configValue)) { + return defaultValue; + } + + Preconditions.checkState(StringUtils.isNumeric(configValue), + String.format("key:%s, value:%s error", configKey, configValue)); + return Integer.parseInt(configValue); + } + + public boolean getBoolProp(String configKey, boolean defaultValue) { + Objects.requireNonNull(configKey, "configKey can not be null"); + + String configValue = StringUtils.deleteWhitespace(getProp(configKey)); + if (StringUtils.isEmpty(configValue)) { + return defaultValue; + } + return Boolean.parseBoolean(configValue); + } + + private String removePrefix(String key, String prefix, boolean removePrefix) { + Objects.requireNonNull(key, "key can not be null"); + Objects.requireNonNull(prefix, "prefix can not be null"); + + String newPrefix = prefix.endsWith(".") ? prefix : prefix + "."; + return removePrefix ? key.replace(newPrefix, "") : key; + } + + public Properties getPropertiesByConfig(String prefix, boolean isRemovePrefix) { + Objects.requireNonNull(prefix, "prefix can not be null"); + + Properties properties = new Properties(); + for (Entry entry : this.properties.entrySet()) { + String key = (String) entry.getKey(); + if (key.startsWith(prefix)) { + properties.put(removePrefix(key, prefix, isRemovePrefix), entry.getValue()); + } + } + return properties; + } + + @SuppressWarnings("unchecked") + public T getPropertiesByConfig(String prefix, Class clazz, boolean removePrefix) { + Objects.requireNonNull(prefix, "prefix can not be null"); + Objects.requireNonNull(clazz, "clazz can not be null"); + + return (T) objectMapper.convertValue(getPropertiesByConfig(prefix, removePrefix), clazz); + } + + public Properties getProperties() { + return this.properties; + } + +} \ No newline at end of file diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/enums/HttpMethod.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/enums/HttpMethod.java new file mode 100644 index 0000000000..75a81b4976 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/enums/HttpMethod.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.enums; + +public enum HttpMethod { + + GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java new file mode 100644 index 0000000000..5e106d05e8 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.exception; + +public class EventMeshException extends RuntimeException { + public static final long serialVersionUID = 5648256502005456586L; + + public EventMeshException(String message) { + super(message); + } + + public EventMeshException(String message, Throwable cause) { + super(message, cause); + } + + public EventMeshException(Throwable cause) { + super(cause); + } + + public EventMeshException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public EventMeshException(Integer errCode, String errMsg) { + super(String.format("errorCode: %s, errorMessage: %s", errCode, errMsg)); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/JsonException.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/JsonException.java new file mode 100644 index 0000000000..2055d6a834 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/JsonException.java @@ -0,0 +1,34 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.exception; + +/** + * Json format exception, see {@link org.apache.eventmesh.common.utils.JsonUtils}. + */ +public class JsonException extends RuntimeException { + + public static final long serialVersionUID = 8611247331715266362L; + + public JsonException(String message) { + super(message); + } + + public JsonException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/file/FileChangeContext.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/file/FileChangeContext.java new file mode 100644 index 0000000000..f46d2bc125 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/file/FileChangeContext.java @@ -0,0 +1,53 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.file; + +import java.nio.file.WatchEvent; + +public class FileChangeContext { + + private String directoryPath; + + private String fileName; + + private WatchEvent watchEvent; + + public String getDirectoryPath() { + return directoryPath; + } + + public void setDirectoryPath(String directoryPath) { + this.directoryPath = directoryPath; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public WatchEvent getWatchEvent() { + return watchEvent; + } + + public void setWatchEvent(WatchEvent watchEvent) { + this.watchEvent = watchEvent; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/file/FileChangeListener.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/file/FileChangeListener.java new file mode 100644 index 0000000000..a11efa9e9c --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/file/FileChangeListener.java @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.file; + +/** + * Users can register {@link FileChangeListener} with WatchFileManager via the + * {@link WatchFileManager#registerFileChangeListener(java.lang.String, org.apache.eventmesh.common.file.FileChangeListener)} method. + * The {@link FileChangeListener#onChanged(org.apache.eventmesh.common.file.FileChangeContext)} method fires when a file changes, + * and the {@link FileChangeListener#support(org.apache.eventmesh.common.file.FileChangeContext)} method let the user customize + * which files are supported + */ +public interface FileChangeListener { + /** + * triggered when a file change occurs + * + * @param changeContext file change context {@link FileChangeContext} + */ + void onChanged(FileChangeContext changeContext); + + /** + * true if support + * + * @param changeContext file change context {@link FileChangeContext} + * @return true if support + */ + boolean support(FileChangeContext changeContext); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/file/WatchFileManager.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/file/WatchFileManager.java new file mode 100644 index 0000000000..86e960eed1 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/file/WatchFileManager.java @@ -0,0 +1,84 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.file; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WatchFileManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(WatchFileManager.class); + + private static final AtomicBoolean CLOSED = new AtomicBoolean(false); + + private static final Map WATCH_FILE_TASK_MAP = new HashMap<>(); + + static { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + LOGGER.warn("[WatchFileManager] WatchFileManager closed"); + shutdown(); + })); + } + + public static void registerFileChangeListener(String directoryPath, + FileChangeListener listener) { + WatchFileTask task = WATCH_FILE_TASK_MAP.get(directoryPath); + if (task == null) { + task = new WatchFileTask(directoryPath); + task.start(); + WATCH_FILE_TASK_MAP.put(directoryPath, task); + } + task.addFileChangeListener(listener); + } + + public static void deregisterFileChangeListener(String directoryPath) { + WatchFileTask task = WATCH_FILE_TASK_MAP.get(directoryPath); + if (task != null) { + task.shutdown(); + WATCH_FILE_TASK_MAP.remove(directoryPath); + } + } + + private static void shutdown() { + if (!CLOSED.compareAndSet(false, true)) { + return; + } + + if (LOGGER.isInfoEnabled()) { + LOGGER.info("[WatchFileManager] start close"); + } + + for (Map.Entry entry : WATCH_FILE_TASK_MAP.entrySet()) { + if (LOGGER.isInfoEnabled()) { + LOGGER.info("[WatchFileManager] start to shutdown : {}", entry.getKey()); + } + + try { + entry.getValue().shutdown(); + } catch (Exception ex) { + LOGGER.error("[WatchFileManager] shutdown has error : ", ex); + } + } + WATCH_FILE_TASK_MAP.clear(); + LOGGER.warn("[WatchFileManager] already closed"); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/file/WatchFileTask.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/file/WatchFileTask.java new file mode 100644 index 0000000000..a585ee2f51 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/file/WatchFileTask.java @@ -0,0 +1,127 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.file; + +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchEvent; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WatchFileTask extends Thread { + + private static final Logger LOGGER = LoggerFactory.getLogger(WatchFileTask.class); + + private static final FileSystem FILE_SYSTEM = FileSystems.getDefault(); + + private final transient WatchService watchService; + + private final transient List fileChangeListeners = new ArrayList<>(); + + private transient volatile boolean watch = true; + + private final transient String directoryPath; + + public WatchFileTask(String directoryPath) { + this.directoryPath = directoryPath; + final Path path = Paths.get(directoryPath); + if (!path.toFile().exists()) { + throw new IllegalArgumentException("file directory not exist: " + directoryPath); + } + if (!path.toFile().isDirectory()) { + throw new IllegalArgumentException("must be a file directory : " + directoryPath); + } + + try (WatchService watchService = FILE_SYSTEM.newWatchService()) { + this.watchService = watchService; + path.register(this.watchService, StandardWatchEventKinds.OVERFLOW, StandardWatchEventKinds.ENTRY_MODIFY, + StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE); + } catch (Exception ex) { + throw new UnsupportedOperationException("WatchService registry fail", ex); + } + } + + public void addFileChangeListener(FileChangeListener fileChangeListener) { + if (fileChangeListener != null) { + fileChangeListeners.add(fileChangeListener); + } + } + + public void shutdown() { + watch = false; + } + + @Override + public void run() { + while (watch) { + try { + WatchKey watchKey = watchService.take(); + List> events = watchKey.pollEvents(); + watchKey.reset(); + + if (events.isEmpty()) { + continue; + } + + for (WatchEvent event : events) { + WatchEvent.Kind kind = event.kind(); + if (kind.equals(StandardWatchEventKinds.OVERFLOW)) { + if (LOGGER.isWarnEnabled()) { + LOGGER.warn("[WatchFileTask] file overflow: {}", event.context()); + } + continue; + } + precessWatchEvent(event); + } + } catch (InterruptedException ex) { + boolean interrupted = Thread.interrupted(); + if (interrupted) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("[WatchFileTask] file watch is interrupted"); + } + } + } catch (Exception ex) { + LOGGER.error("[WatchFileTask] an exception occurred during file listening : ", ex); + } + } + } + + private void precessWatchEvent(WatchEvent event) { + try { + for (FileChangeListener fileChangeListener : fileChangeListeners) { + FileChangeContext context = new FileChangeContext(); + context.setDirectoryPath(directoryPath); + context.setFileName(event.context().toString()); + context.setWatchEvent(event); + if (fileChangeListener.support(context)) { + fileChangeListener.onChanged(context); + } + } + } catch (Exception ex) { + LOGGER.error("[WatchFileTask] file change event callback error : ", ex); + } + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/LoadBalanceSelector.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/LoadBalanceSelector.java new file mode 100644 index 0000000000..3bee08c6ec --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/LoadBalanceSelector.java @@ -0,0 +1,44 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.loadbalance; + +/** + * LoadBalance Interface + * + *

see {@link RandomLoadBalanceSelector} + *

see {@link WeightRoundRobinLoadBalanceSelector} + * + * @param Target type + */ +public interface LoadBalanceSelector { + + /** + * Select one + * + * @return target + */ + T select(); + + /** + * load balance type see {@link LoadBalanceType} + * + * @return load balance type of the selector + */ + LoadBalanceType getType(); + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/LoadBalanceType.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/LoadBalanceType.java new file mode 100644 index 0000000000..6096abdf6b --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/LoadBalanceType.java @@ -0,0 +1,51 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.loadbalance; + +public enum LoadBalanceType { + RANDOM(0, "random load balance strategy"), + WEIGHT_ROUND_ROBIN(1, "weight round robin load balance strategy"), + WEIGHT_RANDOM(2, "weight random load balance strategy"); + + private int code; + private String desc; + + LoadBalanceType(int code, String desc) { + this.code = code; + this.desc = desc; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/RandomLoadBalanceSelector.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/RandomLoadBalanceSelector.java new file mode 100644 index 0000000000..df26897e05 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/RandomLoadBalanceSelector.java @@ -0,0 +1,57 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.loadbalance; + +import org.apache.commons.collections4.CollectionUtils; + +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This selector use random strategy. + * Each selection will randomly give one from the given list + * + * @param Target type + */ +public class RandomLoadBalanceSelector implements LoadBalanceSelector { + + private static final Logger LOG = LoggerFactory.getLogger(RandomLoadBalanceSelector.class); + + private final transient List clusterGroup; + + public RandomLoadBalanceSelector(List clusterGroup) { + this.clusterGroup = clusterGroup; + } + + @Override + public T select() { + if (CollectionUtils.isEmpty(clusterGroup)) { + LOG.warn("No servers available"); + return null; + } + return clusterGroup.get(ThreadLocalRandom.current().nextInt(clusterGroup.size())); + } + + @Override + public LoadBalanceType getType() { + return LoadBalanceType.RANDOM; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/Weight.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/Weight.java new file mode 100644 index 0000000000..880d47ab1f --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/Weight.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.loadbalance; + +import java.util.concurrent.atomic.AtomicInteger; + +public class Weight { + + private T target; + + private final int value; + + private final AtomicInteger currentWeight; + + public Weight(T target, int value) { + this.target = target; + this.value = value; + this.currentWeight = new AtomicInteger(0); + } + + public void decreaseTotal(int total) { + currentWeight.addAndGet(-1 * total); + } + + public void increaseCurrentWeight() { + currentWeight.addAndGet(value); + } + + + public T getTarget() { + return target; + } + + public void setTarget(T target) { + this.target = target; + } + + public int getValue() { + return value; + } + + + public AtomicInteger getCurrentWeight() { + return currentWeight; + } + + @Override + public String toString() { + return "Wight{" + + "target=" + target + + ", value=" + value + + ", currentWeight=" + currentWeight + + '}'; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/WeightRandomLoadBalanceSelector.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/WeightRandomLoadBalanceSelector.java new file mode 100644 index 0000000000..1c5b7ba999 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/WeightRandomLoadBalanceSelector.java @@ -0,0 +1,78 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.loadbalance; + +import org.apache.eventmesh.common.exception.EventMeshException; + +import org.apache.commons.collections4.CollectionUtils; + +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +/** + * This selector use the weighted random strategy to select from list. + * If all the weights are same, it will randomly select one from list. + * If the weights are different, it will select one by using RandomUtils.nextInt(0, w0 + w1 ... + wn) + * + * @param Target type + */ +public class WeightRandomLoadBalanceSelector implements LoadBalanceSelector { + + private final transient List> clusterGroup; + + private final transient int totalWeight; + + private transient boolean sameWeightGroup = true; + + public WeightRandomLoadBalanceSelector(List> clusterGroup) throws EventMeshException { + if (CollectionUtils.isEmpty(clusterGroup)) { + throw new EventMeshException("clusterGroup can not be empty"); + } + int totalWeight = 0; + int firstWeight = clusterGroup.get(0).getValue(); + for (Weight weight : clusterGroup) { + totalWeight += weight.getValue(); + if (sameWeightGroup && firstWeight != weight.getValue()) { + sameWeightGroup = false; + } + } + this.clusterGroup = clusterGroup; + this.totalWeight = totalWeight; + } + + @Override + public T select() { + if (!sameWeightGroup) { + int targetWeight = ThreadLocalRandom.current().nextInt(totalWeight); + for (Weight weight : clusterGroup) { + targetWeight -= weight.getValue(); + if (targetWeight < 0) { + return weight.getTarget(); + } + } + } + + int length = clusterGroup.size(); + return clusterGroup.get(ThreadLocalRandom.current().nextInt(length)).getTarget(); + } + + @Override + public LoadBalanceType getType() { + return LoadBalanceType.WEIGHT_RANDOM; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/WeightRoundRobinLoadBalanceSelector.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/WeightRoundRobinLoadBalanceSelector.java new file mode 100644 index 0000000000..ec90f46b46 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/loadbalance/WeightRoundRobinLoadBalanceSelector.java @@ -0,0 +1,73 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.loadbalance; + +import org.apache.commons.collections4.CollectionUtils; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This selector use the weighted round robin strategy to select from list. + * If the weight is greater, the probability of being selected is larger. + * + * @param Target type + */ +public class WeightRoundRobinLoadBalanceSelector implements LoadBalanceSelector { + + private static final Logger LOG = LoggerFactory.getLogger(WeightRoundRobinLoadBalanceSelector.class); + + private final transient List> clusterGroup; + + private final transient int totalWeight; + + public WeightRoundRobinLoadBalanceSelector(List> clusterGroup) { + int totalWeight = 0; + for (Weight weight : clusterGroup) { + totalWeight += weight.getValue(); + } + this.clusterGroup = clusterGroup; + this.totalWeight = totalWeight; + } + + + @Override + @SuppressWarnings("ConstantConditions") + public T select() { + if (CollectionUtils.isEmpty(clusterGroup)) { + LOG.warn("No servers available"); + return null; + } + Weight targetWeight = null; + for (Weight weight : clusterGroup) { + weight.increaseCurrentWeight(); + if (targetWeight == null || targetWeight.getCurrentWeight().get() < weight.getCurrentWeight().get()) { + targetWeight = weight; + } + } + targetWeight.decreaseTotal(totalWeight); + return targetWeight.getTarget(); + } + + @Override + public LoadBalanceType getType() { + return LoadBalanceType.WEIGHT_ROUND_ROBIN; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/ProtocolTransportObject.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/ProtocolTransportObject.java new file mode 100644 index 0000000000..ca7c36626a --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/ProtocolTransportObject.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol; + +import org.apache.eventmesh.common.protocol.http.HttpCommand; + +import java.io.Serializable; + +/** + *

    + *
  • Tcp transport object{@link org.apache.eventmesh.common.protocol.tcp.Package}
  • + *
  • Http transport object{@link HttpCommand}
  • + *
+ */ +public interface ProtocolTransportObject extends Serializable { +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionItem.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionItem.java new file mode 100644 index 0000000000..469d6d490f --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionItem.java @@ -0,0 +1,97 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol; + +import java.io.Serializable; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.common.base.Objects; + +public class SubscriptionItem implements Serializable { + + public static final long serialVersionUID = 2375640521211793028L; + + private String topic; + + @JsonDeserialize(converter = SubscriptionModeConverter.class) + private SubscriptionMode mode; + + @JsonDeserialize(converter = SubscriptionTypeConverter.class) + private SubscriptionType type; + + public SubscriptionItem() { + } + + public SubscriptionItem(String topic, SubscriptionMode mode, SubscriptionType type) { + this.topic = topic; + this.mode = mode; + this.type = type; + } + + public SubscriptionType getType() { + return type; + } + + public void setType(SubscriptionType type) { + this.type = type; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public SubscriptionMode getMode() { + return mode; + } + + public void setMode(SubscriptionMode mode) { + this.mode = mode; + } + + @Override + public String toString() { + return "SubscriptionItem{" + + "topic=" + topic + + ", mode=" + mode + + ", type=" + type + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SubscriptionItem that = (SubscriptionItem) o; + return Objects.equal(topic, that.topic) && mode == that.mode && type == that.type; + } + + @Override + public int hashCode() { + return Objects.hashCode(topic, mode, type); + } +} + + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionMode.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionMode.java new file mode 100644 index 0000000000..ad4b751a46 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionMode.java @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol; + +public enum SubscriptionMode { + + /** + * broadcast + */ + BROADCASTING("BROADCASTING"), + /** + * clustering + */ + CLUSTERING("CLUSTERING"); + + private String mode; + + SubscriptionMode(String mode) { + this.mode = mode; + } + + public String getMode() { + return mode; + } + + public void setMode(String mode) { + this.mode = mode; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionModeConverter.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionModeConverter.java new file mode 100644 index 0000000000..2b1980f363 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionModeConverter.java @@ -0,0 +1,39 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.type.TypeFactory; +import com.fasterxml.jackson.databind.util.Converter; + +public class SubscriptionModeConverter implements Converter { + @Override + public SubscriptionMode convert(String value) { + return SubscriptionMode.valueOf(value); + } + + @Override + public JavaType getInputType(TypeFactory typeFactory) { + return typeFactory.constructType(String.class); + } + + @Override + public JavaType getOutputType(TypeFactory typeFactory) { + return typeFactory.constructType(SubscriptionMode.class); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionType.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionType.java new file mode 100644 index 0000000000..7efe3089b8 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionType.java @@ -0,0 +1,43 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol; + +public enum SubscriptionType { + /** + * SYNC + */ + SYNC("SYNC"), + /** + * ASYNC + */ + ASYNC("ASYNC"); + + private String type; + + SubscriptionType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionTypeConverter.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionTypeConverter.java new file mode 100644 index 0000000000..50d28914fe --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/SubscriptionTypeConverter.java @@ -0,0 +1,39 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.type.TypeFactory; +import com.fasterxml.jackson.databind.util.Converter; + +public class SubscriptionTypeConverter implements Converter { + @Override + public SubscriptionType convert(String value) { + return SubscriptionType.valueOf(value); + } + + @Override + public JavaType getInputType(TypeFactory typeFactory) { + return typeFactory.constructType(String.class); + } + + @Override + public JavaType getOutputType(TypeFactory typeFactory) { + return typeFactory.constructType(SubscriptionType.class); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/CatalogGrpc.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/CatalogGrpc.java new file mode 100644 index 0000000000..a176da4685 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/CatalogGrpc.java @@ -0,0 +1,385 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.catalog.protos; + +import static io.grpc.MethodDescriptor.generateFullMethodName; + +/** + * + */ +@javax.annotation.Generated( + value = "by gRPC proto compiler (version 1.49.1-SNAPSHOT)", + comments = "Source: catalog.proto") +@io.grpc.stub.annotations.GrpcGenerated +@SuppressWarnings({"all"}) +public final class CatalogGrpc { + + private CatalogGrpc() { + } + + public static final String SERVICE_NAME = "eventmesh.catalog.api.protocol.Catalog"; + + // Static method descriptors that strictly reflect the proto. + private static volatile io.grpc.MethodDescriptor getRegistryMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "Registry", + requestType = RegistryRequest.class, + responseType = RegistryResponse.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getRegistryMethod() { + io.grpc.MethodDescriptor getRegistryMethod; + if ((getRegistryMethod = CatalogGrpc.getRegistryMethod) == null) { + synchronized (CatalogGrpc.class) { + if ((getRegistryMethod = CatalogGrpc.getRegistryMethod) == null) { + CatalogGrpc.getRegistryMethod = getRegistryMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "Registry")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + RegistryRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + RegistryResponse.getDefaultInstance())) + .setSchemaDescriptor(new CatalogMethodDescriptorSupplier("Registry")) + .build(); + } + } + } + return getRegistryMethod; + } + + private static volatile io.grpc.MethodDescriptor getQueryOperationsMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "QueryOperations", + requestType = QueryOperationsRequest.class, + responseType = QueryOperationsResponse.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getQueryOperationsMethod() { + io.grpc.MethodDescriptor getQueryOperationsMethod; + if ((getQueryOperationsMethod = CatalogGrpc.getQueryOperationsMethod) == null) { + synchronized (CatalogGrpc.class) { + if ((getQueryOperationsMethod = CatalogGrpc.getQueryOperationsMethod) == null) { + CatalogGrpc.getQueryOperationsMethod = getQueryOperationsMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "QueryOperations")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + QueryOperationsRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + QueryOperationsResponse.getDefaultInstance())) + .setSchemaDescriptor(new CatalogMethodDescriptorSupplier("QueryOperations")) + .build(); + } + } + } + return getQueryOperationsMethod; + } + + /** + * Creates a new async stub that supports all call types for the service + */ + public static CatalogStub newStub(io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @Override + public CatalogStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new CatalogStub(channel, callOptions); + } + }; + return CatalogStub.newStub(factory, channel); + } + + /** + * Creates a new blocking-style stub that supports unary and streaming output calls on the service + */ + public static CatalogBlockingStub newBlockingStub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @Override + public CatalogBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new CatalogBlockingStub(channel, callOptions); + } + }; + return CatalogBlockingStub.newStub(factory, channel); + } + + /** + * Creates a new ListenableFuture-style stub that supports unary calls on the service + */ + public static CatalogFutureStub newFutureStub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @Override + public CatalogFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new CatalogFutureStub(channel, callOptions); + } + }; + return CatalogFutureStub.newStub(factory, channel); + } + + /** + * + */ + public static abstract class CatalogImplBase implements io.grpc.BindableService { + + /** + * + */ + public void registry(RegistryRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getRegistryMethod(), responseObserver); + } + + /** + * + */ + public void queryOperations(QueryOperationsRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getQueryOperationsMethod(), responseObserver); + } + + @Override + public final io.grpc.ServerServiceDefinition bindService() { + return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) + .addMethod( + getRegistryMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + RegistryRequest, + RegistryResponse>( + this, METHODID_REGISTRY))) + .addMethod( + getQueryOperationsMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + QueryOperationsRequest, + QueryOperationsResponse>( + this, METHODID_QUERY_OPERATIONS))) + .build(); + } + } + + /** + * + */ + public static final class CatalogStub extends io.grpc.stub.AbstractAsyncStub { + private CatalogStub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected CatalogStub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new CatalogStub(channel, callOptions); + } + + /** + * + */ + public void registry(RegistryRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getRegistryMethod(), getCallOptions()), request, responseObserver); + } + + /** + * + */ + public void queryOperations(QueryOperationsRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getQueryOperationsMethod(), getCallOptions()), request, responseObserver); + } + } + + /** + * + */ + public static final class CatalogBlockingStub extends io.grpc.stub.AbstractBlockingStub { + private CatalogBlockingStub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected CatalogBlockingStub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new CatalogBlockingStub(channel, callOptions); + } + + /** + * + */ + public RegistryResponse registry(RegistryRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getRegistryMethod(), getCallOptions(), request); + } + + /** + * + */ + public QueryOperationsResponse queryOperations(QueryOperationsRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getQueryOperationsMethod(), getCallOptions(), request); + } + } + + /** + * + */ + public static final class CatalogFutureStub extends io.grpc.stub.AbstractFutureStub { + private CatalogFutureStub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected CatalogFutureStub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new CatalogFutureStub(channel, callOptions); + } + + /** + * + */ + public com.google.common.util.concurrent.ListenableFuture registry( + RegistryRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getRegistryMethod(), getCallOptions()), request); + } + + /** + * + */ + public com.google.common.util.concurrent.ListenableFuture queryOperations( + QueryOperationsRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getQueryOperationsMethod(), getCallOptions()), request); + } + } + + private static final int METHODID_REGISTRY = 0; + private static final int METHODID_QUERY_OPERATIONS = 1; + + private static final class MethodHandlers implements + io.grpc.stub.ServerCalls.UnaryMethod, + io.grpc.stub.ServerCalls.ServerStreamingMethod, + io.grpc.stub.ServerCalls.ClientStreamingMethod, + io.grpc.stub.ServerCalls.BidiStreamingMethod { + private final CatalogImplBase serviceImpl; + private final int methodId; + + MethodHandlers(CatalogImplBase serviceImpl, int methodId) { + this.serviceImpl = serviceImpl; + this.methodId = methodId; + } + + @Override + @SuppressWarnings("unchecked") + public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + case METHODID_REGISTRY: + serviceImpl.registry((RegistryRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_QUERY_OPERATIONS: + serviceImpl.queryOperations((QueryOperationsRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + default: + throw new AssertionError(); + } + } + + @Override + @SuppressWarnings("unchecked") + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + default: + throw new AssertionError(); + } + } + } + + private static abstract class CatalogBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier { + CatalogBaseDescriptorSupplier() { + } + + @Override + public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { + return EventmeshCatalogGrpc.getDescriptor(); + } + + @Override + public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() { + return getFileDescriptor().findServiceByName("Catalog"); + } + } + + private static final class CatalogFileDescriptorSupplier + extends CatalogBaseDescriptorSupplier { + CatalogFileDescriptorSupplier() { + } + } + + private static final class CatalogMethodDescriptorSupplier + extends CatalogBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoMethodDescriptorSupplier { + private final String methodName; + + CatalogMethodDescriptorSupplier(String methodName) { + this.methodName = methodName; + } + + @Override + public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() { + return getServiceDescriptor().findMethodByName(methodName); + } + } + + private static volatile io.grpc.ServiceDescriptor serviceDescriptor; + + public static io.grpc.ServiceDescriptor getServiceDescriptor() { + io.grpc.ServiceDescriptor result = serviceDescriptor; + if (result == null) { + synchronized (CatalogGrpc.class) { + result = serviceDescriptor; + if (result == null) { + serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) + .setSchemaDescriptor(new CatalogFileDescriptorSupplier()) + .addMethod(getRegistryMethod()) + .addMethod(getQueryOperationsMethod()) + .build(); + } + } + } + return result; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/EventmeshCatalogGrpc.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/EventmeshCatalogGrpc.java new file mode 100644 index 0000000000..38497afa3c --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/EventmeshCatalogGrpc.java @@ -0,0 +1,132 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: catalog.proto + +package org.apache.eventmesh.common.protocol.catalog.protos; + +@SuppressWarnings({"all"}) +public final class EventmeshCatalogGrpc { + private EventmeshCatalogGrpc() { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_catalog_api_protocol_RegistryRequest_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_catalog_api_protocol_RegistryRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_catalog_api_protocol_RegistryResponse_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_catalog_api_protocol_RegistryResponse_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_catalog_api_protocol_QueryOperationsRequest_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_catalog_api_protocol_QueryOperationsRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_catalog_api_protocol_Operation_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_catalog_api_protocol_Operation_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_catalog_api_protocol_QueryOperationsResponse_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_catalog_api_protocol_QueryOperationsResponse_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + + static { + String[] descriptorData = { + "\n\rcatalog.proto\022\036eventmesh.catalog.api.p" + + "rotocol\"8\n\017RegistryRequest\022\021\n\tfile_name\030" + + "\001 \001(\t\022\022\n\ndefinition\030\002 \001(\t\"\022\n\020RegistryRes" + + "ponse\"D\n\026QueryOperationsRequest\022\024\n\014servi" + + "ce_name\030\001 \001(\t\022\024\n\014operation_id\030\002 \001(\t\"?\n\tO" + + "peration\022\024\n\014channel_name\030\001 \001(\t\022\016\n\006schema" + + "\030\002 \001(\t\022\014\n\004type\030\003 \001(\t\"X\n\027QueryOperationsR" + + "esponse\022=\n\noperations\030\001 \003(\0132).eventmesh." + + "catalog.api.protocol.Operation2\201\002\n\007Catal" + + "og\022o\n\010Registry\022/.eventmesh.catalog.api.p" + + "rotocol.RegistryRequest\0320.eventmesh.cata" + + "log.api.protocol.RegistryResponse\"\000\022\204\001\n\017" + + "QueryOperations\0226.eventmesh.catalog.api." + + "protocol.QueryOperationsRequest\0327.eventm" + + "esh.catalog.api.protocol.QueryOperations" + + "Response\"\000B\223\001\n3org.apache.eventmesh.comm" + + "on.protocol.catalog.protosB\024EventmeshCat" + + "alogGrpcP\001ZDgithub.com/apache/incubator-" + + "eventmesh/eventmesh-catalog-go/api/proto" + + "b\006proto3" + }; + descriptor = com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }); + internal_static_eventmesh_catalog_api_protocol_RegistryRequest_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_eventmesh_catalog_api_protocol_RegistryRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_catalog_api_protocol_RegistryRequest_descriptor, + new String[] {"FileName", "Definition",}); + internal_static_eventmesh_catalog_api_protocol_RegistryResponse_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_eventmesh_catalog_api_protocol_RegistryResponse_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_catalog_api_protocol_RegistryResponse_descriptor, + new String[] {}); + internal_static_eventmesh_catalog_api_protocol_QueryOperationsRequest_descriptor = + getDescriptor().getMessageTypes().get(2); + internal_static_eventmesh_catalog_api_protocol_QueryOperationsRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_catalog_api_protocol_QueryOperationsRequest_descriptor, + new String[] {"ServiceName", "OperationId",}); + internal_static_eventmesh_catalog_api_protocol_Operation_descriptor = + getDescriptor().getMessageTypes().get(3); + internal_static_eventmesh_catalog_api_protocol_Operation_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_catalog_api_protocol_Operation_descriptor, + new String[] {"ChannelName", "Schema", "Type",}); + internal_static_eventmesh_catalog_api_protocol_QueryOperationsResponse_descriptor = + getDescriptor().getMessageTypes().get(4); + internal_static_eventmesh_catalog_api_protocol_QueryOperationsResponse_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_catalog_api_protocol_QueryOperationsResponse_descriptor, + new String[] {"Operations",}); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/Operation.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/Operation.java new file mode 100644 index 0000000000..ea5b4d9705 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/Operation.java @@ -0,0 +1,840 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: catalog.proto + +package org.apache.eventmesh.common.protocol.catalog.protos; + +import java.util.Objects; + +import com.google.protobuf.ByteString; +import com.google.protobuf.Internal; + +/** + * Protobuf type {@code eventmesh.catalog.api.protocol.Operation} + */ +@SuppressWarnings({"all"}) +public final class Operation extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.catalog.api.protocol.Operation) + OperationOrBuilder { + private static final long serialVersionUID = 7231240618302324570L; + + public static final int CHANNEL_NAME_FIELD_NUMBER = 1; + public static final int SCHEMA_FIELD_NUMBER = 2; + public static final int TYPE_FIELD_NUMBER = 3; + + private static final Operation DEFAULT_INSTANCE; + + private volatile String channelName; + private volatile String schema; + private volatile String type; + private byte memoizedIsInitialized = -1; + + // Use Operation.newBuilder() to construct. + + + static { + DEFAULT_INSTANCE = new Operation(); + } + + public static Operation getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private Operation(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private Operation() { + channelName = ""; + schema = ""; + type = ""; + } + + @Override + @SuppressWarnings({"unused"}) + protected Object newInstance(UnusedPrivateParameter unused) { + return new Operation(); + } + + @Override + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { + return this.unknownFields; + } + + private Operation( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + + this(); + Objects.requireNonNull(input, "CodedInputStream can not be null"); + Objects.requireNonNull(extensionRegistry, "ExtensionRegistryLite can not be null"); + + if (extensionRegistry == null) { + throw new NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + channelName = input.readStringRequireUtf8(); + break; + } + case 18: { + schema = input.readStringRequireUtf8(); + break; + } + case 26: { + type = input.readStringRequireUtf8(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_Operation_descriptor; + } + + @Override + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_Operation_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Operation.class, Builder.class); + } + + + /** + * string channel_name = 1; + * + * @return The channelName. + */ + @Override + public String getChannelName() { + return channelName; + } + + /** + * string channel_name = 1; + * + * @return The bytes for channelName. + */ + @Override + public com.google.protobuf.ByteString getChannelNameBytes() { + return ByteString.copyFromUtf8(channelName); + } + + + /** + * string schema = 2; + * + * @return The schema. + */ + @Override + public String getSchema() { + return schema; + } + + /** + * string schema = 2; + * + * @return The bytes for schema. + */ + @Override + public com.google.protobuf.ByteString getSchemaBytes() { + + return ByteString.copyFromUtf8(schema); + } + + /** + *
+     * publish/subscribe
+     * 
+ * + * string type = 3; + * + * @return The type. + */ + @Override + public String getType() { + + return type; + } + + /** + *
+     * publish/subscribe
+     * 
+ * + * string type = 3; + * + * @return The bytes for type. + */ + @Override + public com.google.protobuf.ByteString getTypeBytes() { + + return ByteString.copyFromUtf8(type); + } + + + @Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) { + return true; + } + if (isInitialized == 0) { + return false; + } + + memoizedIsInitialized = 1; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getChannelNameBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, channelName); + } + if (!getSchemaBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, schema); + } + if (!getTypeBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, type); + } + unknownFields.writeTo(output); + } + + @Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) { + return size; + } + + size = 0; + if (!getChannelNameBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, channelName); + } + if (!getSchemaBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, schema); + } + if (!getTypeBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, type); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Operation)) { + return super.equals(obj); + } + Operation other = (Operation) obj; + + if (!getChannelName() + .equals(other.getChannelName())) { + return false; + } + if (!getSchema() + .equals(other.getSchema())) { + return false; + } + if (!getType() + .equals(other.getType())) { + return false; + } + if (!unknownFields.equals(other.unknownFields)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + CHANNEL_NAME_FIELD_NUMBER; + hash = (53 * hash) + getChannelName().hashCode(); + hash = (37 * hash) + SCHEMA_FIELD_NUMBER; + hash = (53 * hash) + getSchema().hashCode(); + hash = (37 * hash) + TYPE_FIELD_NUMBER; + hash = (53 * hash) + getType().hashCode(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static Operation parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static Operation parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static Operation parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static Operation parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static Operation parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static Operation parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static Operation parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static Operation parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static Operation parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static Operation parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static Operation parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static Operation parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @Override + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(Operation prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + @Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType(BuilderParent parent) { + return new Builder(parent); + } + + + /** + * Protobuf type {@code eventmesh.catalog.api.protocol.Operation} + */ + public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder + implements OperationOrBuilder { + + private String type = ""; + private String channelName = ""; + private String schema = ""; + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_Operation_descriptor; + } + + @Override + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_Operation_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Operation.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.catalog.protos.Operation.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + + @Override + public Builder clear() { + super.clear(); + channelName = ""; + schema = ""; + type = ""; + return this; + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_Operation_descriptor; + } + + @Override + public Operation getDefaultInstanceForType() { + return Operation.getDefaultInstance(); + } + + @Override + public Operation build() { + Operation result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @Override + public Operation buildPartial() { + Operation result = new Operation(this); + result.channelName = channelName; + result.schema = schema; + result.type = type; + onBuilt(); + return result; + } + + @Override + public Builder clone() { + return super.clone(); + } + + @Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.setField(field, value); + } + + @Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + + @Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + + @Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return super.setRepeatedField(field, index, value); + } + + @Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.addRepeatedField(field, value); + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof Operation) { + return mergeFrom((Operation) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(Operation other) { + if (other == Operation.getDefaultInstance()) { + return this; + } + if (!other.getChannelName().isEmpty()) { + channelName = other.channelName; + onChanged(); + } + if (!other.getSchema().isEmpty()) { + schema = other.schema; + onChanged(); + } + if (!other.getType().isEmpty()) { + type = other.type; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Operation parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (Operation) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + + /** + * string channel_name = 1; + * + * @return The channelName. + */ + public String getChannelName() { + return channelName; + } + + /** + * string channel_name = 1; + * + * @return The bytes for channelName. + */ + public com.google.protobuf.ByteString getChannelNameBytes() { + + return ByteString.copyFromUtf8(channelName); + } + + /** + * string channel_name = 1; + * + * @param value The channelName to set. + * @return This builder for chaining. + */ + public Builder setChannelName(String value) { + Objects.requireNonNull(value, "channelname can not be null"); + + channelName = value; + onChanged(); + return this; + } + + /** + * string channel_name = 1; + * + * @return This builder for chaining. + */ + public Builder clearChannelName() { + channelName = getDefaultInstance().getChannelName(); + onChanged(); + return this; + } + + /** + * string channel_name = 1; + * + * @param value The bytes for channelName to set. + * @return This builder for chaining. + */ + public Builder setChannelNameBytes(com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "channelname can not be null"); + checkByteStringIsUtf8(value); + + channelName = value.toStringUtf8(); + onChanged(); + return this; + } + + /** + * string schema = 2; + * + * @return The schema. + */ + public String getSchema() { + return schema; + } + + /** + * string schema = 2; + * + * @return The bytes for schema. + */ + public com.google.protobuf.ByteString + getSchemaBytes() { + return ByteString.copyFromUtf8(schema); + } + + /** + * string schema = 2; + * + * @param value The schema to set. + * @return This builder for chaining. + */ + public Builder setSchema(String value) { + Objects.requireNonNull(value, "schema can not be null"); + + schema = value; + onChanged(); + return this; + } + + /** + * string schema = 2; + * + * @return This builder for chaining. + */ + public Builder clearSchema() { + schema = getDefaultInstance().getSchema(); + onChanged(); + return this; + } + + /** + * string schema = 2; + * + * @param value The bytes for schema to set. + * @return This builder for chaining. + */ + public Builder setSchemaBytes(com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "schema can not be null"); + checkByteStringIsUtf8(value); + + schema = value.toStringUtf8(); + onChanged(); + return this; + } + + + /** + *
+         * publish/subscribe
+         * 
+ * + * string type = 3; + * + * @return The type. + */ + public String getType() { + + return type; + } + + /** + *
+         * publish/subscribe
+         * 
+ * + * string type = 3; + * + * @return The bytes for type. + */ + public com.google.protobuf.ByteString getTypeBytes() { + return ByteString.copyFromUtf8(type); + } + + /** + *
+         * publish/subscribe
+         * 
+ * + * string type = 3; + * + * @param value The type to set. + * @return This builder for chaining. + */ + public Builder setType(String value) { + Objects.requireNonNull(value, "type can not be null"); + + type = value; + onChanged(); + return this; + } + + /** + *
+         * publish/subscribe
+         * 
+ * + * string type = 3; + * + * @return This builder for chaining. + */ + public Builder clearType() { + type = getDefaultInstance().getType(); + onChanged(); + return this; + } + + /** + *
+         * publish/subscribe
+         * 
+ * + * string type = 3; + * + * @param value The bytes for type to set. + * @return This builder for chaining. + */ + public Builder setTypeBytes(com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "type can not be null"); + checkByteStringIsUtf8(value); + + type = value.toStringUtf8(); + onChanged(); + return this; + } + + @Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.catalog.api.protocol.Operation) + } + + // @@protoc_insertion_point(class_scope:eventmesh.catalog.api.protocol.Operation) + + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @Override + public Operation parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Operation(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @Override + public Operation getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/OperationOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/OperationOrBuilder.java new file mode 100644 index 0000000000..2c610acb4f --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/OperationOrBuilder.java @@ -0,0 +1,80 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: catalog.proto + +package org.apache.eventmesh.common.protocol.catalog.protos; + +@SuppressWarnings({"all"}) +public interface OperationOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.catalog.api.protocol.Operation) + com.google.protobuf.MessageOrBuilder { + + /** + * string channel_name = 1; + * + * @return The channelName. + */ + String getChannelName(); + + /** + * string channel_name = 1; + * + * @return The bytes for channelName. + */ + com.google.protobuf.ByteString + getChannelNameBytes(); + + /** + * string schema = 2; + * + * @return The schema. + */ + String getSchema(); + + /** + * string schema = 2; + * + * @return The bytes for schema. + */ + com.google.protobuf.ByteString + getSchemaBytes(); + + /** + *
+     * publish/subscribe
+     * 
+ * + * string type = 3; + * + * @return The type. + */ + String getType(); + + /** + *
+     * publish/subscribe
+     * 
+ * + * string type = 3; + * + * @return The bytes for type. + */ + com.google.protobuf.ByteString + getTypeBytes(); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/QueryOperationsRequest.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/QueryOperationsRequest.java new file mode 100644 index 0000000000..843b6f3ae0 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/QueryOperationsRequest.java @@ -0,0 +1,786 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: catalog.proto + +package org.apache.eventmesh.common.protocol.catalog.protos; + +/** + * Protobuf type {@code eventmesh.catalog.api.protocol.QueryOperationsRequest} + */ +@SuppressWarnings({"all"}) +public final class QueryOperationsRequest extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.catalog.api.protocol.QueryOperationsRequest) + QueryOperationsRequestOrBuilder { + private static final long serialVersionUID = 0L; + + // Use QueryOperationsRequest.newBuilder() to construct. + private QueryOperationsRequest(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private QueryOperationsRequest() { + serviceName_ = ""; + operationId_ = ""; + } + + @Override + @SuppressWarnings({"unused"}) + protected Object newInstance( + UnusedPrivateParameter unused) { + return new QueryOperationsRequest(); + } + + @Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + + private QueryOperationsRequest( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + String s = input.readStringRequireUtf8(); + + serviceName_ = s; + break; + } + case 18: { + String s = input.readStringRequireUtf8(); + + operationId_ = s; + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_QueryOperationsRequest_descriptor; + } + + @Override + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_QueryOperationsRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + QueryOperationsRequest.class, Builder.class); + } + + public static final int SERVICE_NAME_FIELD_NUMBER = 1; + private volatile Object serviceName_; + + /** + * string service_name = 1; + * + * @return The serviceName. + */ + @Override + public String getServiceName() { + Object ref = serviceName_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + serviceName_ = s; + return s; + } + } + + /** + * string service_name = 1; + * + * @return The bytes for serviceName. + */ + @Override + public com.google.protobuf.ByteString + getServiceNameBytes() { + Object ref = serviceName_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + serviceName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int OPERATION_ID_FIELD_NUMBER = 2; + private volatile Object operationId_; + + /** + * string operation_id = 2; + * + * @return The operationId. + */ + @Override + public String getOperationId() { + Object ref = operationId_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + operationId_ = s; + return s; + } + } + + /** + * string operation_id = 2; + * + * @return The bytes for operationId. + */ + @Override + public com.google.protobuf.ByteString + getOperationIdBytes() { + Object ref = operationId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + operationId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + + @Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) { + return true; + } + if (isInitialized == 0) { + return false; + } + + memoizedIsInitialized = 1; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getServiceNameBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, serviceName_); + } + if (!getOperationIdBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, operationId_); + } + unknownFields.writeTo(output); + } + + @Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) { + return size; + } + + size = 0; + if (!getServiceNameBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, serviceName_); + } + if (!getOperationIdBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, operationId_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof QueryOperationsRequest)) { + return super.equals(obj); + } + QueryOperationsRequest other = (QueryOperationsRequest) obj; + + if (!getServiceName() + .equals(other.getServiceName())) { + return false; + } + if (!getOperationId() + .equals(other.getOperationId())) { + return false; + } + if (!unknownFields.equals(other.unknownFields)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + SERVICE_NAME_FIELD_NUMBER; + hash = (53 * hash) + getServiceName().hashCode(); + hash = (37 * hash) + OPERATION_ID_FIELD_NUMBER; + hash = (53 * hash) + getOperationId().hashCode(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static QueryOperationsRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static QueryOperationsRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static QueryOperationsRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static QueryOperationsRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static QueryOperationsRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static QueryOperationsRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static QueryOperationsRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static QueryOperationsRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static QueryOperationsRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static QueryOperationsRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static QueryOperationsRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static QueryOperationsRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @Override + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(QueryOperationsRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + @Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + return new Builder(parent); + } + + /** + * Protobuf type {@code eventmesh.catalog.api.protocol.QueryOperationsRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.catalog.api.protocol.QueryOperationsRequest) + QueryOperationsRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_QueryOperationsRequest_descriptor; + } + + @Override + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_QueryOperationsRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + QueryOperationsRequest.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.catalog.protos.QueryOperationsRequest.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + + @Override + public Builder clear() { + super.clear(); + serviceName_ = ""; + + operationId_ = ""; + + return this; + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_QueryOperationsRequest_descriptor; + } + + @Override + public QueryOperationsRequest getDefaultInstanceForType() { + return QueryOperationsRequest.getDefaultInstance(); + } + + @Override + public QueryOperationsRequest build() { + QueryOperationsRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @Override + public QueryOperationsRequest buildPartial() { + QueryOperationsRequest result = new QueryOperationsRequest(this); + result.serviceName_ = serviceName_; + result.operationId_ = operationId_; + onBuilt(); + return result; + } + + @Override + public Builder clone() { + return super.clone(); + } + + @Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.setField(field, value); + } + + @Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + + @Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + + @Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return super.setRepeatedField(field, index, value); + } + + @Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.addRepeatedField(field, value); + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof QueryOperationsRequest) { + return mergeFrom((QueryOperationsRequest) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(QueryOperationsRequest other) { + if (other == QueryOperationsRequest.getDefaultInstance()) { + return this; + } + if (!other.getServiceName().isEmpty()) { + serviceName_ = other.serviceName_; + onChanged(); + } + if (!other.getOperationId().isEmpty()) { + operationId_ = other.operationId_; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + QueryOperationsRequest parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (QueryOperationsRequest) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private Object serviceName_ = ""; + + /** + * string service_name = 1; + * + * @return The serviceName. + */ + public String getServiceName() { + Object ref = serviceName_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + serviceName_ = s; + return s; + } else { + return (String) ref; + } + } + + /** + * string service_name = 1; + * + * @return The bytes for serviceName. + */ + public com.google.protobuf.ByteString + getServiceNameBytes() { + Object ref = serviceName_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + serviceName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * string service_name = 1; + * + * @param value The serviceName to set. + * @return This builder for chaining. + */ + public Builder setServiceName( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + serviceName_ = value; + onChanged(); + return this; + } + + /** + * string service_name = 1; + * + * @return This builder for chaining. + */ + public Builder clearServiceName() { + + serviceName_ = getDefaultInstance().getServiceName(); + onChanged(); + return this; + } + + /** + * string service_name = 1; + * + * @param value The bytes for serviceName to set. + * @return This builder for chaining. + */ + public Builder setServiceNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + serviceName_ = value; + onChanged(); + return this; + } + + private Object operationId_ = ""; + + /** + * string operation_id = 2; + * + * @return The operationId. + */ + public String getOperationId() { + Object ref = operationId_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + operationId_ = s; + return s; + } else { + return (String) ref; + } + } + + /** + * string operation_id = 2; + * + * @return The bytes for operationId. + */ + public com.google.protobuf.ByteString + getOperationIdBytes() { + Object ref = operationId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + operationId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * string operation_id = 2; + * + * @param value The operationId to set. + * @return This builder for chaining. + */ + public Builder setOperationId( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + operationId_ = value; + onChanged(); + return this; + } + + /** + * string operation_id = 2; + * + * @return This builder for chaining. + */ + public Builder clearOperationId() { + + operationId_ = getDefaultInstance().getOperationId(); + onChanged(); + return this; + } + + /** + * string operation_id = 2; + * + * @param value The bytes for operationId to set. + * @return This builder for chaining. + */ + public Builder setOperationIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + operationId_ = value; + onChanged(); + return this; + } + + @Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.catalog.api.protocol.QueryOperationsRequest) + } + + // @@protoc_insertion_point(class_scope:eventmesh.catalog.api.protocol.QueryOperationsRequest) + private static final QueryOperationsRequest DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new QueryOperationsRequest(); + } + + public static QueryOperationsRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @Override + public QueryOperationsRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new QueryOperationsRequest(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @Override + public QueryOperationsRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/QueryOperationsRequestOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/QueryOperationsRequestOrBuilder.java new file mode 100644 index 0000000000..b9bd6728a7 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/QueryOperationsRequestOrBuilder.java @@ -0,0 +1,57 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: catalog.proto + +package org.apache.eventmesh.common.protocol.catalog.protos; + +@SuppressWarnings({"all"}) +public interface QueryOperationsRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.catalog.api.protocol.QueryOperationsRequest) + com.google.protobuf.MessageOrBuilder { + + /** + * string service_name = 1; + * + * @return The serviceName. + */ + String getServiceName(); + + /** + * string service_name = 1; + * + * @return The bytes for serviceName. + */ + com.google.protobuf.ByteString + getServiceNameBytes(); + + /** + * string operation_id = 2; + * + * @return The operationId. + */ + String getOperationId(); + + /** + * string operation_id = 2; + * + * @return The bytes for operationId. + */ + com.google.protobuf.ByteString + getOperationIdBytes(); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/QueryOperationsResponse.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/QueryOperationsResponse.java new file mode 100644 index 0000000000..03a7c8c03c --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/QueryOperationsResponse.java @@ -0,0 +1,857 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: catalog.proto + +package org.apache.eventmesh.common.protocol.catalog.protos; + +/** + * Protobuf type {@code eventmesh.catalog.api.protocol.QueryOperationsResponse} + */ +@SuppressWarnings({"all"}) +public final class QueryOperationsResponse extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.catalog.api.protocol.QueryOperationsResponse) + QueryOperationsResponseOrBuilder { + private static final long serialVersionUID = 0L; + + // Use QueryOperationsResponse.newBuilder() to construct. + private QueryOperationsResponse(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private QueryOperationsResponse() { + operations_ = java.util.Collections.emptyList(); + } + + @Override + @SuppressWarnings({"unused"}) + protected Object newInstance( + UnusedPrivateParameter unused) { + return new QueryOperationsResponse(); + } + + @Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + + private QueryOperationsResponse( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + if (!((mutable_bitField0_ & 0x00000001) != 0)) { + operations_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000001; + } + operations_.add( + input.readMessage(Operation.parser(), extensionRegistry)); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000001) != 0)) { + operations_ = java.util.Collections.unmodifiableList(operations_); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_QueryOperationsResponse_descriptor; + } + + @Override + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_QueryOperationsResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + QueryOperationsResponse.class, Builder.class); + } + + public static final int OPERATIONS_FIELD_NUMBER = 1; + private java.util.List operations_; + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + @Override + public java.util.List getOperationsList() { + return operations_; + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + @Override + public java.util.List + getOperationsOrBuilderList() { + return operations_; + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + @Override + public int getOperationsCount() { + return operations_.size(); + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + @Override + public Operation getOperations(int index) { + return operations_.get(index); + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + @Override + public OperationOrBuilder getOperationsOrBuilder( + int index) { + return operations_.get(index); + } + + private byte memoizedIsInitialized = -1; + + @Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) { + return true; + } + if (isInitialized == 0) { + return false; + } + + memoizedIsInitialized = 1; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + for (Operation operation : operations_) { + output.writeMessage(1, operation); + } + unknownFields.writeTo(output); + } + + @Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) { + return size; + } + + size = 0; + for (Operation operation : operations_) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, operation); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof QueryOperationsResponse)) { + return super.equals(obj); + } + QueryOperationsResponse other = (QueryOperationsResponse) obj; + + if (!getOperationsList() + .equals(other.getOperationsList())) { + return false; + } + if (!unknownFields.equals(other.unknownFields)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (getOperationsCount() > 0) { + hash = (37 * hash) + OPERATIONS_FIELD_NUMBER; + hash = (53 * hash) + getOperationsList().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static QueryOperationsResponse parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static QueryOperationsResponse parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static QueryOperationsResponse parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static QueryOperationsResponse parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static QueryOperationsResponse parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static QueryOperationsResponse parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static QueryOperationsResponse parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static QueryOperationsResponse parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static QueryOperationsResponse parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static QueryOperationsResponse parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static QueryOperationsResponse parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static QueryOperationsResponse parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @Override + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(QueryOperationsResponse prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + @Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + return new Builder(parent); + } + + /** + * Protobuf type {@code eventmesh.catalog.api.protocol.QueryOperationsResponse} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.catalog.api.protocol.QueryOperationsResponse) + QueryOperationsResponseOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_QueryOperationsResponse_descriptor; + } + + @Override + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_QueryOperationsResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + QueryOperationsResponse.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.catalog.protos.QueryOperationsResponse.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getOperationsFieldBuilder(); + } + } + + @Override + public Builder clear() { + super.clear(); + if (operationsBuilder_ == null) { + operations_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + } else { + operationsBuilder_.clear(); + } + return this; + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_QueryOperationsResponse_descriptor; + } + + @Override + public QueryOperationsResponse getDefaultInstanceForType() { + return QueryOperationsResponse.getDefaultInstance(); + } + + @Override + public QueryOperationsResponse build() { + QueryOperationsResponse result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @Override + public QueryOperationsResponse buildPartial() { + QueryOperationsResponse result = new QueryOperationsResponse(this); + int from_bitField0_ = bitField0_; + if (operationsBuilder_ == null) { + if (((bitField0_ & 0x00000001) != 0)) { + operations_ = java.util.Collections.unmodifiableList(operations_); + bitField0_ = (bitField0_ & ~0x00000001); + } + result.operations_ = operations_; + } else { + result.operations_ = operationsBuilder_.build(); + } + onBuilt(); + return result; + } + + @Override + public Builder clone() { + return super.clone(); + } + + @Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.setField(field, value); + } + + @Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + + @Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + + @Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return super.setRepeatedField(field, index, value); + } + + @Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.addRepeatedField(field, value); + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof QueryOperationsResponse) { + return mergeFrom((QueryOperationsResponse) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(QueryOperationsResponse other) { + if (other == QueryOperationsResponse.getDefaultInstance()) { + return this; + } + if (operationsBuilder_ == null) { + if (!other.operations_.isEmpty()) { + if (operations_.isEmpty()) { + operations_ = other.operations_; + bitField0_ = (bitField0_ & ~0x00000001); + } else { + ensureOperationsIsMutable(); + operations_.addAll(other.operations_); + } + onChanged(); + } + } else { + if (!other.operations_.isEmpty()) { + if (operationsBuilder_.isEmpty()) { + operationsBuilder_.dispose(); + operationsBuilder_ = null; + operations_ = other.operations_; + bitField0_ = (bitField0_ & ~0x00000001); + operationsBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getOperationsFieldBuilder() : null; + } else { + operationsBuilder_.addAllMessages(other.operations_); + } + } + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + QueryOperationsResponse parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (QueryOperationsResponse) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private int bitField0_; + + private java.util.List operations_ = + java.util.Collections.emptyList(); + + private void ensureOperationsIsMutable() { + if (!((bitField0_ & 0x00000001) != 0)) { + operations_ = new java.util.ArrayList(operations_); + bitField0_ |= 0x00000001; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + Operation, Operation.Builder, OperationOrBuilder> operationsBuilder_; + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public java.util.List getOperationsList() { + if (operationsBuilder_ == null) { + return java.util.Collections.unmodifiableList(operations_); + } else { + return operationsBuilder_.getMessageList(); + } + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public int getOperationsCount() { + if (operationsBuilder_ == null) { + return operations_.size(); + } else { + return operationsBuilder_.getCount(); + } + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Operation getOperations(int index) { + if (operationsBuilder_ == null) { + return operations_.get(index); + } else { + return operationsBuilder_.getMessage(index); + } + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Builder setOperations( + int index, Operation value) { + if (operationsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureOperationsIsMutable(); + operations_.set(index, value); + onChanged(); + } else { + operationsBuilder_.setMessage(index, value); + } + return this; + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Builder setOperations( + int index, Operation.Builder builderForValue) { + if (operationsBuilder_ == null) { + ensureOperationsIsMutable(); + operations_.set(index, builderForValue.build()); + onChanged(); + } else { + operationsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Builder addOperations(Operation value) { + if (operationsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureOperationsIsMutable(); + operations_.add(value); + onChanged(); + } else { + operationsBuilder_.addMessage(value); + } + return this; + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Builder addOperations( + int index, Operation value) { + if (operationsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureOperationsIsMutable(); + operations_.add(index, value); + onChanged(); + } else { + operationsBuilder_.addMessage(index, value); + } + return this; + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Builder addOperations( + Operation.Builder builderForValue) { + if (operationsBuilder_ == null) { + ensureOperationsIsMutable(); + operations_.add(builderForValue.build()); + onChanged(); + } else { + operationsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Builder addOperations( + int index, Operation.Builder builderForValue) { + if (operationsBuilder_ == null) { + ensureOperationsIsMutable(); + operations_.add(index, builderForValue.build()); + onChanged(); + } else { + operationsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Builder addAllOperations( + Iterable values) { + if (operationsBuilder_ == null) { + ensureOperationsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, operations_); + onChanged(); + } else { + operationsBuilder_.addAllMessages(values); + } + return this; + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Builder clearOperations() { + if (operationsBuilder_ == null) { + operations_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + } else { + operationsBuilder_.clear(); + } + return this; + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Builder removeOperations(int index) { + if (operationsBuilder_ == null) { + ensureOperationsIsMutable(); + operations_.remove(index); + onChanged(); + } else { + operationsBuilder_.remove(index); + } + return this; + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Operation.Builder getOperationsBuilder( + int index) { + return getOperationsFieldBuilder().getBuilder(index); + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public OperationOrBuilder getOperationsOrBuilder( + int index) { + if (operationsBuilder_ == null) { + return operations_.get(index); + } else { + return operationsBuilder_.getMessageOrBuilder(index); + } + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public java.util.List + getOperationsOrBuilderList() { + if (operationsBuilder_ != null) { + return operationsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(operations_); + } + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Operation.Builder addOperationsBuilder() { + return getOperationsFieldBuilder().addBuilder( + Operation.getDefaultInstance()); + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public Operation.Builder addOperationsBuilder( + int index) { + return getOperationsFieldBuilder().addBuilder( + index, Operation.getDefaultInstance()); + } + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + public java.util.List + getOperationsBuilderList() { + return getOperationsFieldBuilder().getBuilderList(); + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + Operation, Operation.Builder, OperationOrBuilder> + getOperationsFieldBuilder() { + if (operationsBuilder_ == null) { + operationsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + Operation, Operation.Builder, OperationOrBuilder>( + operations_, + ((bitField0_ & 0x00000001) != 0), + getParentForChildren(), + isClean()); + operations_ = null; + } + return operationsBuilder_; + } + + @Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.catalog.api.protocol.QueryOperationsResponse) + } + + // @@protoc_insertion_point(class_scope:eventmesh.catalog.api.protocol.QueryOperationsResponse) + private static final QueryOperationsResponse DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new QueryOperationsResponse(); + } + + public static QueryOperationsResponse getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @Override + public QueryOperationsResponse parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new QueryOperationsResponse(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @Override + public QueryOperationsResponse getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/QueryOperationsResponseOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/QueryOperationsResponseOrBuilder.java new file mode 100644 index 0000000000..818c970fa9 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/QueryOperationsResponseOrBuilder.java @@ -0,0 +1,55 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: catalog.proto + +package org.apache.eventmesh.common.protocol.catalog.protos; + +@SuppressWarnings({"all"}) +public interface QueryOperationsResponseOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.catalog.api.protocol.QueryOperationsResponse) + com.google.protobuf.MessageOrBuilder { + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + java.util.List + getOperationsList(); + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + Operation getOperations(int index); + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + int getOperationsCount(); + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + java.util.List + getOperationsOrBuilderList(); + + /** + * repeated .eventmesh.catalog.api.protocol.Operation operations = 1; + */ + OperationOrBuilder getOperationsOrBuilder( + int index); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/RegistryRequest.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/RegistryRequest.java new file mode 100644 index 0000000000..b80ad2f5ea --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/RegistryRequest.java @@ -0,0 +1,701 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: catalog.proto + +package org.apache.eventmesh.common.protocol.catalog.protos; + +import java.util.Objects; + +import com.google.protobuf.ByteString; + +/** + * Protobuf type {@code eventmesh.catalog.api.protocol.RegistryRequest} + */ +@SuppressWarnings({"all"}) +public final class RegistryRequest extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.catalog.api.protocol.RegistryRequest) + RegistryRequestOrBuilder { + private static final long serialVersionUID = 3745623108415722309L; + + // Use RegistryRequest.newBuilder() to construct. + private RegistryRequest(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private RegistryRequest() { + fileName_ = ""; + definition_ = ""; + } + + @Override + @SuppressWarnings({"unused"}) + protected Object newInstance( + UnusedPrivateParameter unused) { + return new RegistryRequest(); + } + + @Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + + private RegistryRequest( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + Objects.requireNonNull(input, "CodedInputStream can not be null"); + Objects.requireNonNull(extensionRegistry, "ExtensionRegistryLite can not be null"); + + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + fileName_ = input.readStringRequireUtf8(); + break; + } + case 18: { + definition_ = input.readStringRequireUtf8(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_RegistryRequest_descriptor; + } + + @Override + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_RegistryRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + RegistryRequest.class, Builder.class); + } + + public static final int FILE_NAME_FIELD_NUMBER = 1; + private volatile String fileName_; + + /** + * string file_name = 1; + * + * @return The fileName. + */ + @Override + public String getFileName() { + return fileName_; + } + + /** + * string file_name = 1; + * + * @return The bytes for fileName. + */ + @Override + public com.google.protobuf.ByteString getFileNameBytes() { + return ByteString.copyFromUtf8(fileName_); + } + + public static final int DEFINITION_FIELD_NUMBER = 2; + private volatile String definition_; + + /** + * string definition = 2; + * + * @return The definition. + */ + @Override + public String getDefinition() { + return definition_; + } + + /** + * string definition = 2; + * + * @return The bytes for definition. + */ + @Override + public com.google.protobuf.ByteString + getDefinitionBytes() { + return ByteString.copyFromUtf8(definition_); + } + + private byte memoizedIsInitialized = -1; + + @Override + public final boolean isInitialized() { + if (memoizedIsInitialized == 1) { + return true; + } + if (memoizedIsInitialized == 0) { + return false; + } + + memoizedIsInitialized = 1; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getFileNameBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, fileName_); + } + if (!getDefinitionBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, definition_); + } + unknownFields.writeTo(output); + } + + @Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) { + return size; + } + + size = 0; + if (!getFileNameBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, fileName_); + } + if (!getDefinitionBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, definition_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof RegistryRequest)) { + return super.equals(obj); + } + RegistryRequest other = (RegistryRequest) obj; + + if (!getFileName() + .equals(other.getFileName()) + || !getDefinition() + .equals(other.getDefinition()) + || !unknownFields.equals(other.unknownFields)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + FILE_NAME_FIELD_NUMBER; + hash = (53 * hash) + getFileName().hashCode(); + hash = (37 * hash) + DEFINITION_FIELD_NUMBER; + hash = (53 * hash) + getDefinition().hashCode(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static RegistryRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static RegistryRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static RegistryRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static RegistryRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static RegistryRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static RegistryRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static RegistryRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static RegistryRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static RegistryRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static RegistryRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static RegistryRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static RegistryRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @Override + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(RegistryRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + @Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + + /** + * Protobuf type {@code eventmesh.catalog.api.protocol.RegistryRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.catalog.api.protocol.RegistryRequest) + RegistryRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_RegistryRequest_descriptor; + } + + @Override + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_RegistryRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + RegistryRequest.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.catalog.protos.RegistryRequest.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder(BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + + @Override + public Builder clear() { + super.clear(); + fileName_ = ""; + + definition_ = ""; + + return this; + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_RegistryRequest_descriptor; + } + + @Override + public RegistryRequest getDefaultInstanceForType() { + return RegistryRequest.getDefaultInstance(); + } + + @Override + public RegistryRequest build() { + RegistryRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @Override + public RegistryRequest buildPartial() { + RegistryRequest result = new RegistryRequest(this); + result.fileName_ = fileName_; + result.definition_ = definition_; + onBuilt(); + return result; + } + + @Override + public Builder clone() { + return super.clone(); + } + + @Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.setField(field, value); + } + + @Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + + @Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + + @Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return super.setRepeatedField(field, index, value); + } + + @Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.addRepeatedField(field, value); + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof RegistryRequest) { + return mergeFrom((RegistryRequest) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(RegistryRequest other) { + if (other == RegistryRequest.getDefaultInstance()) { + return this; + } + if (!other.getFileName().isEmpty()) { + fileName_ = other.fileName_; + onChanged(); + } + if (!other.getDefinition().isEmpty()) { + definition_ = other.definition_; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + RegistryRequest parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (RegistryRequest) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private String fileName_ = ""; + + /** + * string file_name = 1; + * + * @return The fileName. + */ + public String getFileName() { + return fileName_; + } + + /** + * string file_name = 1; + * + * @return The bytes for fileName. + */ + public com.google.protobuf.ByteString + getFileNameBytes() { + return ByteString.copyFromUtf8(fileName_); + } + + /** + * string file_name = 1; + * + * @param value The fileName to set. + * @return This builder for chaining. + */ + public Builder setFileName( + String value) { + Objects.requireNonNull(value, "FileName can not be null"); + + fileName_ = value; + onChanged(); + return this; + } + + /** + * string file_name = 1; + * + * @return This builder for chaining. + */ + public Builder clearFileName() { + + fileName_ = getDefaultInstance().getFileName(); + onChanged(); + return this; + } + + /** + * string file_name = 1; + * + * @param value The bytes for fileName to set. + * @return This builder for chaining. + */ + public Builder setFileNameBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "FileNameBytes can not be null"); + checkByteStringIsUtf8(value); + + fileName_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String definition_ = ""; + + /** + * string definition = 2; + * + * @return The definition. + */ + public String getDefinition() { + return definition_; + } + + /** + * string definition = 2; + * + * @return The bytes for definition. + */ + public com.google.protobuf.ByteString + getDefinitionBytes() { + return ByteString.copyFromUtf8(definition_); + } + + /** + * string definition = 2; + * + * @param value The definition to set. + * @return This builder for chaining. + */ + public Builder setDefinition( + String value) { + Objects.requireNonNull(value, "Definition can not be null"); + + definition_ = value; + onChanged(); + return this; + } + + /** + * string definition = 2; + * + * @return This builder for chaining. + */ + public Builder clearDefinition() { + + definition_ = getDefaultInstance().getDefinition(); + onChanged(); + return this; + } + + /** + * string definition = 2; + * + * @param value The bytes for definition to set. + * @return This builder for chaining. + */ + public Builder setDefinitionBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "DefinitionBytes can not be null"); + checkByteStringIsUtf8(value); + + definition_ = value.toStringUtf8(); + onChanged(); + return this; + } + + @Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.catalog.api.protocol.RegistryRequest) + } + + // @@protoc_insertion_point(class_scope:eventmesh.catalog.api.protocol.RegistryRequest) + private static final RegistryRequest DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new RegistryRequest(); + } + + public static RegistryRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @Override + public RegistryRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new RegistryRequest(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @Override + public RegistryRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/RegistryRequestOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/RegistryRequestOrBuilder.java new file mode 100644 index 0000000000..82cbf9d857 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/RegistryRequestOrBuilder.java @@ -0,0 +1,57 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: catalog.proto + +package org.apache.eventmesh.common.protocol.catalog.protos; + +@SuppressWarnings({"all"}) +public interface RegistryRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.catalog.api.protocol.RegistryRequest) + com.google.protobuf.MessageOrBuilder { + + /** + * string file_name = 1; + * + * @return The fileName. + */ + String getFileName(); + + /** + * string file_name = 1; + * + * @return The bytes for fileName. + */ + com.google.protobuf.ByteString + getFileNameBytes(); + + /** + * string definition = 2; + * + * @return The definition. + */ + String getDefinition(); + + /** + * string definition = 2; + * + * @return The bytes for definition. + */ + com.google.protobuf.ByteString + getDefinitionBytes(); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/RegistryResponse.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/RegistryResponse.java new file mode 100644 index 0000000000..3aa0e1c43b --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/RegistryResponse.java @@ -0,0 +1,478 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: catalog.proto + +package org.apache.eventmesh.common.protocol.catalog.protos; + +import java.util.Objects; + +/** + * Protobuf type {@code eventmesh.catalog.api.protocol.RegistryResponse} + */ +@SuppressWarnings({"all"}) +public final class RegistryResponse extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.catalog.api.protocol.RegistryResponse) + RegistryResponseOrBuilder { + private static final long serialVersionUID = 5690543722366991453L; + + // Use RegistryResponse.newBuilder() to construct. + private RegistryResponse(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private RegistryResponse() { + } + + @Override + @SuppressWarnings({"unused"}) + protected Object newInstance( + UnusedPrivateParameter unused) { + return new RegistryResponse(); + } + + @Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + + private RegistryResponse( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + Objects.requireNonNull(input, "CodedInputStream can not be null"); + Objects.requireNonNull(extensionRegistry, "ExtensionRegistryLite can not be null"); + + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_RegistryResponse_descriptor; + } + + @Override + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_RegistryResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + RegistryResponse.class, Builder.class); + } + + private byte memoizedIsInitialized = -1; + + @Override + public final boolean isInitialized() { + if (memoizedIsInitialized == 1) { + return true; + } + if (memoizedIsInitialized == 0) { + return false; + } + + memoizedIsInitialized = 1; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + unknownFields.writeTo(output); + } + + @Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) { + return size; + } + + size = 0; + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return memoizedSize; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof RegistryResponse)) { + return super.equals(obj); + } + RegistryResponse other = (RegistryResponse) obj; + + if (!unknownFields.equals(other.unknownFields)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static RegistryResponse parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static RegistryResponse parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static RegistryResponse parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static RegistryResponse parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static RegistryResponse parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static RegistryResponse parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static RegistryResponse parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static RegistryResponse parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static RegistryResponse parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static RegistryResponse parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static RegistryResponse parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static RegistryResponse parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @Override + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(RegistryResponse prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + @Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType(BuilderParent parent) { + return new Builder(parent); + } + + /** + * Protobuf type {@code eventmesh.catalog.api.protocol.RegistryResponse} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.catalog.api.protocol.RegistryResponse) + RegistryResponseOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_RegistryResponse_descriptor; + } + + @Override + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_RegistryResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + RegistryResponse.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.catalog.protos.RegistryResponse.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + + @Override + public Builder clear() { + super.clear(); + return this; + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshCatalogGrpc.internal_static_eventmesh_catalog_api_protocol_RegistryResponse_descriptor; + } + + @Override + public RegistryResponse getDefaultInstanceForType() { + return RegistryResponse.getDefaultInstance(); + } + + @Override + public RegistryResponse build() { + RegistryResponse result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @Override + public RegistryResponse buildPartial() { + RegistryResponse result = new RegistryResponse(this); + onBuilt(); + return result; + } + + @Override + public Builder clone() { + return super.clone(); + } + + @Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.setField(field, value); + } + + @Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + + @Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + + @Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return super.setRepeatedField(field, index, value); + } + + @Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.addRepeatedField(field, value); + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof RegistryResponse) { + return mergeFrom((RegistryResponse) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(RegistryResponse other) { + if (other == RegistryResponse.getDefaultInstance()) { + return this; + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + RegistryResponse parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (RegistryResponse) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + @Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.catalog.api.protocol.RegistryResponse) + } + + // @@protoc_insertion_point(class_scope:eventmesh.catalog.api.protocol.RegistryResponse) + private static final RegistryResponse DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new RegistryResponse(); + } + + public static RegistryResponse getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @Override + public RegistryResponse parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new RegistryResponse(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @Override + public RegistryResponse getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/RegistryResponseOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/RegistryResponseOrBuilder.java new file mode 100644 index 0000000000..a0d8f0520c --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/catalog/protos/RegistryResponseOrBuilder.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: catalog.proto + +package org.apache.eventmesh.common.protocol.catalog.protos; + +@SuppressWarnings({"all"}) +public interface RegistryResponseOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.catalog.api.protocol.RegistryResponse) + com.google.protobuf.MessageOrBuilder { +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/common/BatchMessageWrapper.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/common/BatchMessageWrapper.java new file mode 100644 index 0000000000..0f67b42275 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/common/BatchMessageWrapper.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.grpc.common; + +import org.apache.eventmesh.common.protocol.ProtocolTransportObject; +import org.apache.eventmesh.common.protocol.grpc.protos.BatchMessage; + +public class BatchMessageWrapper implements ProtocolTransportObject { + public static final long serialVersionUID = 7658452608197650205L; + + private final BatchMessage batchMessage; + + public BatchMessageWrapper(BatchMessage batchMessage) { + this.batchMessage = batchMessage; + } + + public BatchMessage getMessage() { + return batchMessage; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/common/ProtocolKey.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/common/ProtocolKey.java new file mode 100644 index 0000000000..0294ce1c54 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/common/ProtocolKey.java @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.grpc.common; + +public class ProtocolKey { + + public static final String ENV = "env"; + public static final String IDC = "idc"; + public static final String SYS = "sys"; + public static final String PID = "pid"; + public static final String IP = "ip"; + public static final String USERNAME = "username"; + public static final String PASSWD = "passwd"; + public static final String LANGUAGE = "language"; + + public static final String PROTOCOL_TYPE = "protocoltype"; + public static final String PROTOCOL_VERSION = "protocolversion"; + public static final String PROTOCOL_DESC = "protocoldesc"; + + public static final String SEQ_NUM = "seqnum"; + public static final String UNIQUE_ID = "uniqueid"; + public static final String TTL = "ttl"; + public static final String PRODUCERGROUP = "producergroup"; + public static final String TAG = "tag"; + + public static final String CONTENT_TYPE = "contenttype"; +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/common/SimpleMessageWrapper.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/common/SimpleMessageWrapper.java new file mode 100644 index 0000000000..bae6653b88 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/common/SimpleMessageWrapper.java @@ -0,0 +1,36 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.grpc.common; + +import org.apache.eventmesh.common.protocol.ProtocolTransportObject; +import org.apache.eventmesh.common.protocol.grpc.protos.SimpleMessage; + +public class SimpleMessageWrapper implements ProtocolTransportObject { + + public static final long serialVersionUID = 6679584345416493607L; + + private final SimpleMessage simpleMessage; + + public SimpleMessageWrapper(SimpleMessage simpleMessage) { + this.simpleMessage = simpleMessage; + } + + public SimpleMessage getMessage() { + return simpleMessage; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/common/StatusCode.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/common/StatusCode.java new file mode 100644 index 0000000000..e7cf9a37f4 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/common/StatusCode.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.grpc.common; + +public enum StatusCode { + + SUCCESS("0", "success"), + OVERLOAD("1", "eventMesh overload, try later, "), + EVENTMESH_REQUESTCODE_INVALID("2", "requestCode can't be null, or must be number, "), + EVENTMESH_SEND_SYNC_MSG_ERR("3", "eventMesh send rr msg err, "), + EVENTMESH_WAITING_RR_MSG_ERR("4", "eventMesh waiting rr msg err, "), + EVENTMESH_PROTOCOL_HEADER_ERR("6", "eventMesh protocol[header] err, "), + EVENTMESH_PROTOCOL_BODY_ERR("7", "eventMesh protocol[body] err, "), + EVENTMESH_STOP("8", "eventMesh will stop or had stopped, "), + EVENTMESH_REJECT_BY_PROCESSOR_ERROR("9", "eventMesh reject by processor error, "), + EVENTMESH_BATCH_PUBLISH_ERR("10", "eventMesh batch publish messages error, "), + EVENTMESH_SEND_BATCHLOG_MSG_ERR("17", "eventMesh send batchlog msg err, "), + EVENTMESH_BATCH_SPEED_OVER_LIMIT_ERR("11", "eventMesh batch msg speed over the limit, "), + EVENTMESH_PACKAGE_MSG_ERR("12", "eventMesh package msg err, "), + EVENTMESH_GROUP_PRODUCER_STOPED_ERR("13", "eventMesh group producer stopped, "), + EVENTMESH_SEND_ASYNC_MSG_ERR("14", "eventMesh send async msg err, "), + EVENTMESH_REPLY_MSG_ERR("15", "eventMesh reply msg err, "), + EVENTMESH_RUNTIME_ERR("16", "eventMesh runtime err, "), + EVENTMESH_SUBSCRIBE_ERR("17", "eventMesh subscribe err"), + EVENTMESH_UNSUBSCRIBE_ERR("18", "eventMesh unsubscribe err"), + EVENTMESH_HEARTBEAT_ERR("19", "eventMesh heartbeat err"), + EVENTMESH_ACL_ERR("20", "eventMesh acl err"), + EVENTMESH_SEND_MESSAGE_SPEED_OVER_LIMIT_ERR("21", "eventMesh send message speed over the limit err."), + EVENTMESH_REQUEST_REPLY_MSG_ERR("22", "eventMesh request reply msg err, "), + CLIENT_RESUBSCRIBE("30", "client needs to resubscribe."); + + private String retCode; + + private String errMsg; + + StatusCode(String retCode, String errMsg) { + this.retCode = retCode; + this.errMsg = errMsg; + } + + public String getRetCode() { + return retCode; + } + + public void setRetCode(String retCode) { + this.retCode = retCode; + } + + public String getErrMsg() { + return errMsg; + } + + public void setErrMsg(String errMsg) { + this.errMsg = errMsg; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/BatchMessage.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/BatchMessage.java new file mode 100644 index 0000000000..7cee369c8b --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/BatchMessage.java @@ -0,0 +1,2462 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +import java.util.Objects; + +import com.google.protobuf.ByteString; + +/** + * Protobuf type {@code eventmesh.common.protocol.grpc.BatchMessage} + */ +@SuppressWarnings({"all"}) +public final class BatchMessage extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.common.protocol.grpc.BatchMessage) + BatchMessageOrBuilder { + private static final long serialVersionUID = -3876605571602481461L; + + // Use BatchMessage.newBuilder() to construct. + private BatchMessage(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private BatchMessage() { + producerGroup_ = ""; + topic_ = ""; + messageItem_ = java.util.Collections.emptyList(); + } + + @Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + + private BatchMessage( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownFieldProto3( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + RequestHeader.Builder subBuilder = null; + if (header_ != null) { + subBuilder = header_.toBuilder(); + } + header_ = input.readMessage(RequestHeader.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(header_); + header_ = subBuilder.buildPartial(); + } + + break; + } + case 18: { + producerGroup_ = input.readStringRequireUtf8(); + break; + } + case 26: { + topic_ = input.readStringRequireUtf8(); + break; + } + case 34: { + if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) { + messageItem_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000008; + } + messageItem_.add( + input.readMessage(MessageItem.parser(), extensionRegistry)); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) { + messageItem_ = java.util.Collections.unmodifiableList(messageItem_); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_BatchMessage_descriptor; + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_BatchMessage_fieldAccessorTable + .ensureFieldAccessorsInitialized( + BatchMessage.class, Builder.class); + } + + public interface MessageItemOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.common.protocol.grpc.BatchMessage.MessageItem) + com.google.protobuf.MessageOrBuilder { + + /** + * string content = 1; + */ + String getContent(); + + /** + * string content = 1; + */ + com.google.protobuf.ByteString + getContentBytes(); + + /** + * string ttl = 2; + */ + String getTtl(); + + /** + * string ttl = 2; + */ + com.google.protobuf.ByteString + getTtlBytes(); + + /** + * string uniqueId = 3; + */ + String getUniqueId(); + + /** + * string uniqueId = 3; + */ + com.google.protobuf.ByteString + getUniqueIdBytes(); + + /** + * string seqNum = 4; + */ + String getSeqNum(); + + /** + * string seqNum = 4; + */ + com.google.protobuf.ByteString + getSeqNumBytes(); + + /** + * string tag = 5; + */ + String getTag(); + + /** + * string tag = 5; + */ + com.google.protobuf.ByteString + getTagBytes(); + + /** + * map<string, string> properties = 6; + */ + int getPropertiesCount(); + + /** + * map<string, string> properties = 6; + */ + boolean containsProperties( + String key); + + /** + * Use {@link #getPropertiesMap()} instead. + */ + @Deprecated + java.util.Map + getProperties(); + + /** + * map<string, string> properties = 6; + */ + java.util.Map + getPropertiesMap(); + + /** + * map<string, string> properties = 6; + */ + + String getPropertiesOrDefault( + String key, + String defaultValue); + + /** + * map<string, string> properties = 6; + */ + + String getPropertiesOrThrow( + String key); + } + + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.BatchMessage.MessageItem} + */ + public static final class MessageItem extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.common.protocol.grpc.BatchMessage.MessageItem) + MessageItemOrBuilder { + private static final long serialVersionUID = -6677110210488831851L; + + // Use MessageItem.newBuilder() to construct. + private MessageItem(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private MessageItem() { + content_ = ""; + ttl_ = ""; + uniqueId_ = ""; + seqNum_ = ""; + tag_ = ""; + } + + @Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + + private MessageItem( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownFieldProto3( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + content_ = input.readStringRequireUtf8(); + break; + } + case 18: { + ttl_ = input.readStringRequireUtf8(); + break; + } + case 26: { + uniqueId_ = input.readStringRequireUtf8(); + break; + } + case 34: { + seqNum_ = input.readStringRequireUtf8(); + break; + } + case 42: { + tag_ = input.readStringRequireUtf8(); + break; + } + case 50: { + if (!((mutable_bitField0_ & 0x00000020) == 0x00000020)) { + properties_ = com.google.protobuf.MapField.newMapField( + PropertiesDefaultEntryHolder.defaultEntry); + mutable_bitField0_ |= 0x00000020; + } + com.google.protobuf.MapEntry + properties__ = input.readMessage( + PropertiesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + properties_.getMutableMap().put( + properties__.getKey(), properties__.getValue()); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMapField( + int number) { + switch (number) { + case 6: + return internalGetProperties(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_fieldAccessorTable + .ensureFieldAccessorsInitialized( + MessageItem.class, Builder.class); + } + + private int bitField0_; + public static final int CONTENT_FIELD_NUMBER = 1; + private volatile String content_; + + /** + * string content = 1; + */ + public String getContent() { + return content_; + } + + /** + * string content = 1; + */ + public com.google.protobuf.ByteString + getContentBytes() { + return ByteString.copyFromUtf8(content_); + } + + public static final int TTL_FIELD_NUMBER = 2; + private volatile String ttl_; + + /** + * string ttl = 2; + */ + public String getTtl() { + return ttl_; + } + + /** + * string ttl = 2; + */ + public com.google.protobuf.ByteString + getTtlBytes() { + return ByteString.copyFromUtf8(ttl_); + } + + public static final int UNIQUEID_FIELD_NUMBER = 3; + private volatile String uniqueId_; + + /** + * string uniqueId = 3; + */ + public String getUniqueId() { + return uniqueId_; + } + + /** + * string uniqueId = 3; + */ + public com.google.protobuf.ByteString + getUniqueIdBytes() { + return ByteString.copyFromUtf8(uniqueId_); + } + + public static final int SEQNUM_FIELD_NUMBER = 4; + private volatile String seqNum_; + + /** + * string seqNum = 4; + */ + public String getSeqNum() { + return seqNum_; + } + + /** + * string seqNum = 4; + */ + public com.google.protobuf.ByteString + getSeqNumBytes() { + return ByteString.copyFromUtf8(seqNum_); + } + + public static final int TAG_FIELD_NUMBER = 5; + private volatile String tag_; + + /** + * string tag = 5; + */ + public String getTag() { + return tag_; + } + + /** + * string tag = 5; + */ + public com.google.protobuf.ByteString + getTagBytes() { + return ByteString.copyFromUtf8(tag_); + } + + public static final int PROPERTIES_FIELD_NUMBER = 6; + + private static final class PropertiesDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + String, String> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_PropertiesEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.STRING, + ""); + } + + private com.google.protobuf.MapField< + String, String> properties_; + + private com.google.protobuf.MapField + internalGetProperties() { + if (properties_ == null) { + return com.google.protobuf.MapField.emptyMapField( + PropertiesDefaultEntryHolder.defaultEntry); + } + return properties_; + } + + public int getPropertiesCount() { + return internalGetProperties().getMap().size(); + } + + /** + * map<string, string> properties = 6; + */ + + public boolean containsProperties( + String key) { + Objects.requireNonNull(key, "key can not be null"); + + return internalGetProperties().getMap().containsKey(key); + } + + /** + * Use {@link #getPropertiesMap()} instead. + */ + @Deprecated + public java.util.Map getProperties() { + return getPropertiesMap(); + } + + /** + * map<string, string> properties = 6; + */ + + public java.util.Map getPropertiesMap() { + return internalGetProperties().getMap(); + } + + /** + * map<string, string> properties = 6; + */ + + public String getPropertiesOrDefault( + String key, + String defaultValue) { + Objects.requireNonNull(key, "key can not be null"); + + java.util.Map map = + internalGetProperties().getMap(); + String value = map.get(key); + if (value == null) return defaultValue; + return value; + } + + /** + * map<string, string> properties = 6; + */ + + public String getPropertiesOrThrow( + String key) { + Objects.requireNonNull(key, "key can not be null"); + + java.util.Map map = + internalGetProperties().getMap(); + if (!map.containsKey(key)) { + throw new IllegalArgumentException(); + } + return map.get(key); + } + + private byte memoizedIsInitialized = -1; + + public final boolean isInitialized() { + if (memoizedIsInitialized == 1) return true; + if (memoizedIsInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getContentBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, content_); + } + if (!getTtlBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, ttl_); + } + if (!getUniqueIdBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, uniqueId_); + } + if (!getSeqNumBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 4, seqNum_); + } + if (!getTagBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 5, tag_); + } + com.google.protobuf.GeneratedMessageV3 + .serializeStringMapTo( + output, + internalGetProperties(), + PropertiesDefaultEntryHolder.defaultEntry, + 6); + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getContentBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, content_); + } + if (!getTtlBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, ttl_); + } + if (!getUniqueIdBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, uniqueId_); + } + if (!getSeqNumBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, seqNum_); + } + if (!getTagBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(5, tag_); + } + for (java.util.Map.Entry entry + : internalGetProperties().getMap().entrySet()) { + com.google.protobuf.MapEntry + properties__ = PropertiesDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, properties__); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof MessageItem)) { + return super.equals(obj); + } + MessageItem other = (MessageItem) obj; + + return getContent() + .equals(other.getContent()) + && getTtl() + .equals(other.getTtl()) + && getUniqueId() + .equals(other.getUniqueId()) + && getSeqNum() + .equals(other.getSeqNum()) + && getTag() + .equals(other.getTag()) + && internalGetProperties().equals( + other.internalGetProperties()) + && unknownFields.equals(other.unknownFields); + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + CONTENT_FIELD_NUMBER; + hash = (53 * hash) + getContent().hashCode(); + hash = (37 * hash) + TTL_FIELD_NUMBER; + hash = (53 * hash) + getTtl().hashCode(); + hash = (37 * hash) + UNIQUEID_FIELD_NUMBER; + hash = (53 * hash) + getUniqueId().hashCode(); + hash = (37 * hash) + SEQNUM_FIELD_NUMBER; + hash = (53 * hash) + getSeqNum().hashCode(); + hash = (37 * hash) + TAG_FIELD_NUMBER; + hash = (53 * hash) + getTag().hashCode(); + if (!internalGetProperties().getMap().isEmpty()) { + hash = (37 * hash) + PROPERTIES_FIELD_NUMBER; + hash = (53 * hash) + internalGetProperties().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static MessageItem parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static MessageItem parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static MessageItem parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static MessageItem parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static MessageItem parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static MessageItem parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static MessageItem parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static MessageItem parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static MessageItem parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static MessageItem parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static MessageItem parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static MessageItem parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(MessageItem prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + return new Builder(parent); + } + + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.BatchMessage.MessageItem} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.common.protocol.grpc.BatchMessage.MessageItem) + MessageItemOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMapField( + int number) { + switch (number) { + case 6: + return internalGetProperties(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMutableMapField( + int number) { + switch (number) { + case 6: + return internalGetMutableProperties(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_fieldAccessorTable + .ensureFieldAccessorsInitialized( + MessageItem.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.grpc.protos.BatchMessage.MessageItem.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder(BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + + public Builder clear() { + super.clear(); + content_ = ""; + ttl_ = ""; + uniqueId_ = ""; + seqNum_ = ""; + tag_ = ""; + internalGetMutableProperties().clear(); + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_descriptor; + } + + public MessageItem getDefaultInstanceForType() { + return MessageItem.getDefaultInstance(); + } + + public MessageItem build() { + MessageItem result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public MessageItem buildPartial() { + MessageItem result = new MessageItem(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + result.content_ = content_; + result.ttl_ = ttl_; + result.uniqueId_ = uniqueId_; + result.seqNum_ = seqNum_; + result.tag_ = tag_; + result.properties_ = internalGetProperties(); + result.properties_.makeImmutable(); + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder clone() { + return (Builder) super.clone(); + } + + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.setField(field, value); + } + + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return (Builder) super.clearField(field); + } + + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return (Builder) super.clearOneof(oneof); + } + + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return (Builder) super.setRepeatedField(field, index, value); + } + + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.addRepeatedField(field, value); + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof MessageItem) { + return mergeFrom((MessageItem) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(MessageItem other) { + if (other == MessageItem.getDefaultInstance()) return this; + if (!other.getContent().isEmpty()) { + content_ = other.content_; + onChanged(); + } + if (!other.getTtl().isEmpty()) { + ttl_ = other.ttl_; + onChanged(); + } + if (!other.getUniqueId().isEmpty()) { + uniqueId_ = other.uniqueId_; + onChanged(); + } + if (!other.getSeqNum().isEmpty()) { + seqNum_ = other.seqNum_; + onChanged(); + } + if (!other.getTag().isEmpty()) { + tag_ = other.tag_; + onChanged(); + } + internalGetMutableProperties().mergeFrom( + other.internalGetProperties()); + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + MessageItem parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (MessageItem) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private int bitField0_; + + private String content_ = ""; + + /** + * string content = 1; + */ + public String getContent() { + return content_; + } + + /** + * string content = 1; + */ + public com.google.protobuf.ByteString + getContentBytes() { + return ByteString.copyFromUtf8(content_); + } + + /** + * string content = 1; + */ + public Builder setContent( + String value) { + Objects.requireNonNull(value, "content can not be null"); + + content_ = value; + onChanged(); + return this; + } + + /** + * string content = 1; + */ + public Builder clearContent() { + + content_ = getDefaultInstance().getContent(); + onChanged(); + return this; + } + + /** + * string content = 1; + */ + public Builder setContentBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "ContentBytes can not be null"); + checkByteStringIsUtf8(value); + + content_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String ttl_ = ""; + + /** + * string ttl = 2; + */ + public String getTtl() { + return ttl_; + } + + /** + * string ttl = 2; + */ + public com.google.protobuf.ByteString + getTtlBytes() { + return ByteString.copyFromUtf8(ttl_); + } + + /** + * string ttl = 2; + */ + public Builder setTtl( + String value) { + Objects.requireNonNull(value, "ttl can not be null"); + + ttl_ = value; + onChanged(); + return this; + } + + /** + * string ttl = 2; + */ + public Builder clearTtl() { + + ttl_ = getDefaultInstance().getTtl(); + onChanged(); + return this; + } + + /** + * string ttl = 2; + */ + public Builder setTtlBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "TtlBytes can not be null"); + checkByteStringIsUtf8(value); + + ttl_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String uniqueId_ = ""; + + /** + * string uniqueId = 3; + */ + public String getUniqueId() { + return uniqueId_; + } + + /** + * string uniqueId = 3; + */ + public com.google.protobuf.ByteString + getUniqueIdBytes() { + return ByteString.copyFromUtf8(uniqueId_); + } + + /** + * string uniqueId = 3; + */ + public Builder setUniqueId( + String value) { + Objects.requireNonNull(value, "uniqueId_ can not be null"); + + uniqueId_ = value; + onChanged(); + return this; + } + + /** + * string uniqueId = 3; + */ + public Builder clearUniqueId() { + + uniqueId_ = getDefaultInstance().getUniqueId(); + onChanged(); + return this; + } + + /** + * string uniqueId = 3; + */ + public Builder setUniqueIdBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "UniqueIdBytes can not be null"); + checkByteStringIsUtf8(value); + + uniqueId_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String seqNum_ = ""; + + /** + * string seqNum = 4; + */ + public String getSeqNum() { + return seqNum_; + } + + /** + * string seqNum = 4; + */ + public com.google.protobuf.ByteString + getSeqNumBytes() { + return ByteString.copyFromUtf8(seqNum_); + } + + /** + * string seqNum = 4; + */ + public Builder setSeqNum( + String value) { + Objects.requireNonNull(value, "SeqNum can not be null"); + + seqNum_ = value; + onChanged(); + return this; + } + + /** + * string seqNum = 4; + */ + public Builder clearSeqNum() { + + seqNum_ = getDefaultInstance().getSeqNum(); + onChanged(); + return this; + } + + /** + * string seqNum = 4; + */ + public Builder setSeqNumBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "SeqNumBytes can not be null"); + checkByteStringIsUtf8(value); + + seqNum_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String tag_ = ""; + + /** + * string tag = 5; + */ + public String getTag() { + return tag_; + } + + /** + * string tag = 5; + */ + public com.google.protobuf.ByteString + getTagBytes() { + return ByteString.copyFromUtf8(tag_); + } + + /** + * string tag = 5; + */ + public Builder setTag( + String value) { + Objects.requireNonNull(value, "tag can not be null"); + + tag_ = value; + onChanged(); + return this; + } + + /** + * string tag = 5; + */ + public Builder clearTag() { + + tag_ = getDefaultInstance().getTag(); + onChanged(); + return this; + } + + /** + * string tag = 5; + */ + public Builder setTagBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "TagBytes can not be null"); + checkByteStringIsUtf8(value); + + tag_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private com.google.protobuf.MapField< + String, String> properties_; + + private com.google.protobuf.MapField + internalGetProperties() { + if (properties_ == null) { + return com.google.protobuf.MapField.emptyMapField( + PropertiesDefaultEntryHolder.defaultEntry); + } + return properties_; + } + + private com.google.protobuf.MapField + internalGetMutableProperties() { + onChanged(); + ; + if (properties_ == null) { + properties_ = com.google.protobuf.MapField.newMapField( + PropertiesDefaultEntryHolder.defaultEntry); + } + if (!properties_.isMutable()) { + properties_ = properties_.copy(); + } + return properties_; + } + + public int getPropertiesCount() { + return internalGetProperties().getMap().size(); + } + + /** + * map<string, string> properties = 6; + */ + + public boolean containsProperties( + String key) { + Objects.requireNonNull(key, "key can not be null"); + + return internalGetProperties().getMap().containsKey(key); + } + + /** + * Use {@link #getPropertiesMap()} instead. + */ + @Deprecated + public java.util.Map getProperties() { + return getPropertiesMap(); + } + + /** + * map<string, string> properties = 6; + */ + + public java.util.Map getPropertiesMap() { + return internalGetProperties().getMap(); + } + + /** + * map<string, string> properties = 6; + */ + + public String getPropertiesOrDefault( + String key, + String defaultValue) { + Objects.requireNonNull(key, "key can not be null"); + + java.util.Map map = + internalGetProperties().getMap(); + String value = map.get(key); + if (value == null) return defaultValue; + return value; + } + + /** + * map<string, string> properties = 6; + */ + + public String getPropertiesOrThrow( + String key) { + Objects.requireNonNull(key, "key can not be null"); + + java.util.Map map = + internalGetProperties().getMap(); + if (!map.containsKey(key)) { + throw new IllegalArgumentException(); + } + return map.get(key); + } + + public Builder clearProperties() { + internalGetMutableProperties().getMutableMap() + .clear(); + return this; + } + + /** + * map<string, string> properties = 6; + */ + + public Builder removeProperties( + String key) { + Objects.requireNonNull(key, "key can not be null"); + + internalGetMutableProperties().getMutableMap() + .remove(key); + return this; + } + + /** + * Use alternate mutation accessors instead. + */ + @Deprecated + public java.util.Map + getMutableProperties() { + return internalGetMutableProperties().getMutableMap(); + } + + /** + * map<string, string> properties = 6; + */ + public Builder putProperties( + String key, + String value) { + Objects.requireNonNull(key, "key can not be null"); + Objects.requireNonNull(value, "value can not be null"); + + internalGetMutableProperties().getMutableMap() + .put(key, value); + return this; + } + + /** + * map<string, string> properties = 6; + */ + + public Builder putAllProperties( + java.util.Map values) { + internalGetMutableProperties().getMutableMap() + .putAll(values); + return this; + } + + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFieldsProto3(unknownFields); + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.common.protocol.grpc.BatchMessage.MessageItem) + } + + // @@protoc_insertion_point(class_scope:eventmesh.common.protocol.grpc.BatchMessage.MessageItem) + private static final MessageItem DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new MessageItem(); + } + + public static MessageItem getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public MessageItem parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new MessageItem(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public MessageItem getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private int bitField0_; + public static final int HEADER_FIELD_NUMBER = 1; + private RequestHeader header_; + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public boolean hasHeader() { + return header_ != null; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeader getHeader() { + return header_ == null ? RequestHeader.getDefaultInstance() : header_; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeaderOrBuilder getHeaderOrBuilder() { + return getHeader(); + } + + public static final int PRODUCERGROUP_FIELD_NUMBER = 2; + private volatile String producerGroup_; + + /** + * string producerGroup = 2; + */ + public String getProducerGroup() { + return producerGroup_; + } + + /** + * string producerGroup = 2; + */ + public com.google.protobuf.ByteString + getProducerGroupBytes() { + return ByteString.copyFromUtf8(producerGroup_); + } + + public static final int TOPIC_FIELD_NUMBER = 3; + private volatile String topic_; + + /** + * string topic = 3; + */ + public String getTopic() { + return topic_; + } + + /** + * string topic = 3; + */ + public com.google.protobuf.ByteString + getTopicBytes() { + return ByteString.copyFromUtf8(topic_); + } + + public static final int MESSAGEITEM_FIELD_NUMBER = 4; + private java.util.List messageItem_; + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public java.util.List getMessageItemList() { + return messageItem_; + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public java.util.List + getMessageItemOrBuilderList() { + return messageItem_; + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public int getMessageItemCount() { + return messageItem_.size(); + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public MessageItem getMessageItem(int index) { + return messageItem_.get(index); + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public MessageItemOrBuilder getMessageItemOrBuilder( + int index) { + return messageItem_.get(index); + } + + private byte memoizedIsInitialized = -1; + + public final boolean isInitialized() { + if (memoizedIsInitialized == 1) return true; + if (memoizedIsInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (header_ != null) { + output.writeMessage(1, getHeader()); + } + if (!getProducerGroupBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, producerGroup_); + } + if (!getTopicBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, topic_); + } + for (int i = 0; i < messageItem_.size(); i++) { + output.writeMessage(4, messageItem_.get(i)); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + size += (header_ != null ? + com.google.protobuf.CodedOutputStream.computeMessageSize(1, getHeader()) : 0) + + + (!getProducerGroupBytes().isEmpty() ? + com.google.protobuf.GeneratedMessageV3.computeStringSize(2, producerGroup_) : 0) + + + (!getTopicBytes().isEmpty() ? + com.google.protobuf.GeneratedMessageV3.computeStringSize(3, topic_) : 0); + + for (int i = 0; i < messageItem_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, messageItem_.get(i)); + } + + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return memoizedSize; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof BatchMessage)) { + return super.equals(obj); + } + BatchMessage other = (BatchMessage) obj; + + return (hasHeader() == other.hasHeader()) + && (hasHeader() ? getHeader().equals(other.getHeader()) : true) + && getProducerGroup().equals(other.getProducerGroup()) + && getTopic().equals(other.getTopic()) + && getMessageItemList().equals(other.getMessageItemList()) + && unknownFields.equals(other.unknownFields); + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasHeader()) { + hash = (37 * hash) + HEADER_FIELD_NUMBER; + hash = (53 * hash) + getHeader().hashCode(); + } + hash = (37 * hash) + PRODUCERGROUP_FIELD_NUMBER; + hash = (53 * hash) + getProducerGroup().hashCode(); + hash = (37 * hash) + TOPIC_FIELD_NUMBER; + hash = (53 * hash) + getTopic().hashCode(); + if (getMessageItemCount() > 0) { + hash = (37 * hash) + MESSAGEITEM_FIELD_NUMBER; + hash = (53 * hash) + getMessageItemList().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static BatchMessage parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static BatchMessage parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static BatchMessage parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static BatchMessage parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static BatchMessage parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static BatchMessage parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static BatchMessage parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static BatchMessage parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static BatchMessage parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static BatchMessage parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static BatchMessage parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static BatchMessage parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(BatchMessage prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.BatchMessage} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.common.protocol.grpc.BatchMessage) + BatchMessageOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_BatchMessage_descriptor; + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_BatchMessage_fieldAccessorTable + .ensureFieldAccessorsInitialized( + BatchMessage.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.grpc.protos.BatchMessage.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder(BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getMessageItemFieldBuilder(); + } + } + + public Builder clear() { + super.clear(); + if (headerBuilder_ == null) { + header_ = null; + } else { + header_ = null; + headerBuilder_ = null; + } + producerGroup_ = ""; + + topic_ = ""; + + if (messageItemBuilder_ == null) { + messageItem_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000008); + } else { + messageItemBuilder_.clear(); + } + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_BatchMessage_descriptor; + } + + public BatchMessage getDefaultInstanceForType() { + return BatchMessage.getDefaultInstance(); + } + + public BatchMessage build() { + BatchMessage result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public BatchMessage buildPartial() { + BatchMessage result = new BatchMessage(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (headerBuilder_ == null) { + result.header_ = header_; + } else { + result.header_ = headerBuilder_.build(); + } + result.producerGroup_ = producerGroup_; + result.topic_ = topic_; + if (messageItemBuilder_ == null) { + if (((bitField0_ & 0x00000008) == 0x00000008)) { + messageItem_ = java.util.Collections.unmodifiableList(messageItem_); + bitField0_ = (bitField0_ & ~0x00000008); + } + result.messageItem_ = messageItem_; + } else { + result.messageItem_ = messageItemBuilder_.build(); + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder clone() { + return (Builder) super.clone(); + } + + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.setField(field, value); + } + + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return (Builder) super.clearField(field); + } + + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return (Builder) super.clearOneof(oneof); + } + + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return (Builder) super.setRepeatedField(field, index, value); + } + + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.addRepeatedField(field, value); + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof BatchMessage) { + return mergeFrom((BatchMessage) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(BatchMessage other) { + if (other == BatchMessage.getDefaultInstance()) return this; + if (other.hasHeader()) { + mergeHeader(other.getHeader()); + } + if (!other.getProducerGroup().isEmpty()) { + producerGroup_ = other.producerGroup_; + onChanged(); + } + if (!other.getTopic().isEmpty()) { + topic_ = other.topic_; + onChanged(); + } + if (messageItemBuilder_ == null) { + if (!other.messageItem_.isEmpty()) { + if (messageItem_.isEmpty()) { + messageItem_ = other.messageItem_; + bitField0_ = (bitField0_ & ~0x00000008); + } else { + ensureMessageItemIsMutable(); + messageItem_.addAll(other.messageItem_); + } + onChanged(); + } + } else { + if (!other.messageItem_.isEmpty()) { + if (messageItemBuilder_.isEmpty()) { + messageItemBuilder_.dispose(); + messageItemBuilder_ = null; + messageItem_ = other.messageItem_; + bitField0_ = (bitField0_ & ~0x00000008); + messageItemBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getMessageItemFieldBuilder() : null; + } else { + messageItemBuilder_.addAllMessages(other.messageItem_); + } + } + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + BatchMessage parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (BatchMessage) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private int bitField0_; + + private RequestHeader header_ = null; + private com.google.protobuf.SingleFieldBuilderV3< + RequestHeader, RequestHeader.Builder, RequestHeaderOrBuilder> headerBuilder_; + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public boolean hasHeader() { + return headerBuilder_ != null || header_ != null; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeader getHeader() { + if (headerBuilder_ == null) { + return header_ == null ? RequestHeader.getDefaultInstance() : header_; + } else { + return headerBuilder_.getMessage(); + } + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder setHeader(RequestHeader value) { + if (headerBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + header_ = value; + onChanged(); + } else { + headerBuilder_.setMessage(value); + } + + return this; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder setHeader( + RequestHeader.Builder builderForValue) { + if (headerBuilder_ == null) { + header_ = builderForValue.build(); + onChanged(); + } else { + headerBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder mergeHeader(RequestHeader value) { + if (headerBuilder_ == null) { + if (header_ != null) { + header_ = + RequestHeader.newBuilder(header_).mergeFrom(value).buildPartial(); + } else { + header_ = value; + } + onChanged(); + } else { + headerBuilder_.mergeFrom(value); + } + + return this; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder clearHeader() { + if (headerBuilder_ == null) { + header_ = null; + onChanged(); + } else { + header_ = null; + headerBuilder_ = null; + } + + return this; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeader.Builder getHeaderBuilder() { + + onChanged(); + return getHeaderFieldBuilder().getBuilder(); + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeaderOrBuilder getHeaderOrBuilder() { + if (headerBuilder_ != null) { + return headerBuilder_.getMessageOrBuilder(); + } else { + return header_ == null ? + RequestHeader.getDefaultInstance() : header_; + } + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + private com.google.protobuf.SingleFieldBuilderV3< + RequestHeader, RequestHeader.Builder, RequestHeaderOrBuilder> + getHeaderFieldBuilder() { + if (headerBuilder_ == null) { + headerBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + RequestHeader, RequestHeader.Builder, RequestHeaderOrBuilder>( + getHeader(), + getParentForChildren(), + isClean()); + header_ = null; + } + return headerBuilder_; + } + + private String producerGroup_ = ""; + + /** + * string producerGroup = 2; + */ + public String getProducerGroup() { + return producerGroup_; + } + + /** + * string producerGroup = 2; + */ + public com.google.protobuf.ByteString + getProducerGroupBytes() { + return ByteString.copyFromUtf8(producerGroup_); + } + + /** + * string producerGroup = 2; + */ + public Builder setProducerGroup( + String value) { + Objects.requireNonNull(value, "ProducerGroup can not be null"); + + producerGroup_ = value; + onChanged(); + return this; + } + + /** + * string producerGroup = 2; + */ + public Builder clearProducerGroup() { + + producerGroup_ = getDefaultInstance().getProducerGroup(); + onChanged(); + return this; + } + + /** + * string producerGroup = 2; + */ + public Builder setProducerGroupBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "ProducerGroupBytes can not be null"); + checkByteStringIsUtf8(value); + + producerGroup_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String topic_ = ""; + + /** + * string topic = 3; + */ + public String getTopic() { + return topic_; + } + + /** + * string topic = 3; + */ + public com.google.protobuf.ByteString + getTopicBytes() { + return ByteString.copyFromUtf8(topic_); + } + + /** + * string topic = 3; + */ + public Builder setTopic( + String value) { + Objects.requireNonNull(value, "Topic can not be null"); + + topic_ = value; + onChanged(); + return this; + } + + /** + * string topic = 3; + */ + public Builder clearTopic() { + + topic_ = getDefaultInstance().getTopic(); + onChanged(); + return this; + } + + /** + * string topic = 3; + */ + public Builder setTopicBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "TopicBytes can not be null"); + checkByteStringIsUtf8(value); + + topic_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private java.util.List messageItem_ = + java.util.Collections.emptyList(); + + private void ensureMessageItemIsMutable() { + if (!((bitField0_ & 0x00000008) == 0x00000008)) { + messageItem_ = new java.util.ArrayList(messageItem_); + bitField0_ |= 0x00000008; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + MessageItem, MessageItem.Builder, MessageItemOrBuilder> messageItemBuilder_; + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public java.util.List getMessageItemList() { + if (messageItemBuilder_ == null) { + return java.util.Collections.unmodifiableList(messageItem_); + } else { + return messageItemBuilder_.getMessageList(); + } + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public int getMessageItemCount() { + if (messageItemBuilder_ == null) { + return messageItem_.size(); + } else { + return messageItemBuilder_.getCount(); + } + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public MessageItem getMessageItem(int index) { + if (messageItemBuilder_ == null) { + return messageItem_.get(index); + } else { + return messageItemBuilder_.getMessage(index); + } + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public Builder setMessageItem( + int index, MessageItem value) { + if (messageItemBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureMessageItemIsMutable(); + messageItem_.set(index, value); + onChanged(); + } else { + messageItemBuilder_.setMessage(index, value); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public Builder setMessageItem( + int index, MessageItem.Builder builderForValue) { + if (messageItemBuilder_ == null) { + ensureMessageItemIsMutable(); + messageItem_.set(index, builderForValue.build()); + onChanged(); + } else { + messageItemBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public Builder addMessageItem(MessageItem value) { + if (messageItemBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureMessageItemIsMutable(); + messageItem_.add(value); + onChanged(); + } else { + messageItemBuilder_.addMessage(value); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public Builder addMessageItem( + int index, MessageItem value) { + if (messageItemBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureMessageItemIsMutable(); + messageItem_.add(index, value); + onChanged(); + } else { + messageItemBuilder_.addMessage(index, value); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public Builder addMessageItem( + MessageItem.Builder builderForValue) { + if (messageItemBuilder_ == null) { + ensureMessageItemIsMutable(); + messageItem_.add(builderForValue.build()); + onChanged(); + } else { + messageItemBuilder_.addMessage(builderForValue.build()); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public Builder addMessageItem( + int index, MessageItem.Builder builderForValue) { + if (messageItemBuilder_ == null) { + ensureMessageItemIsMutable(); + messageItem_.add(index, builderForValue.build()); + onChanged(); + } else { + messageItemBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public Builder addAllMessageItem( + Iterable values) { + if (messageItemBuilder_ == null) { + ensureMessageItemIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, messageItem_); + onChanged(); + } else { + messageItemBuilder_.addAllMessages(values); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public Builder clearMessageItem() { + if (messageItemBuilder_ == null) { + messageItem_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000008); + onChanged(); + } else { + messageItemBuilder_.clear(); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public Builder removeMessageItem(int index) { + if (messageItemBuilder_ == null) { + ensureMessageItemIsMutable(); + messageItem_.remove(index); + onChanged(); + } else { + messageItemBuilder_.remove(index); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public MessageItem.Builder getMessageItemBuilder( + int index) { + return getMessageItemFieldBuilder().getBuilder(index); + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public MessageItemOrBuilder getMessageItemOrBuilder( + int index) { + if (messageItemBuilder_ == null) { + return messageItem_.get(index); + } else { + return messageItemBuilder_.getMessageOrBuilder(index); + } + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public java.util.List + getMessageItemOrBuilderList() { + if (messageItemBuilder_ != null) { + return messageItemBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(messageItem_); + } + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public MessageItem.Builder addMessageItemBuilder() { + return getMessageItemFieldBuilder().addBuilder( + MessageItem.getDefaultInstance()); + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public MessageItem.Builder addMessageItemBuilder( + int index) { + return getMessageItemFieldBuilder().addBuilder( + index, MessageItem.getDefaultInstance()); + } + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + public java.util.List + getMessageItemBuilderList() { + return getMessageItemFieldBuilder().getBuilderList(); + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + MessageItem, MessageItem.Builder, MessageItemOrBuilder> + getMessageItemFieldBuilder() { + if (messageItemBuilder_ == null) { + messageItemBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + MessageItem, MessageItem.Builder, MessageItemOrBuilder>( + messageItem_, + ((bitField0_ & 0x00000008) == 0x00000008), + getParentForChildren(), + isClean()); + messageItem_ = null; + } + return messageItemBuilder_; + } + + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFieldsProto3(unknownFields); + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.common.protocol.grpc.BatchMessage) + } + + // @@protoc_insertion_point(class_scope:eventmesh.common.protocol.grpc.BatchMessage) + private static final BatchMessage DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new BatchMessage(); + } + + public static BatchMessage getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public BatchMessage parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new BatchMessage(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public BatchMessage getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/BatchMessageOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/BatchMessageOrBuilder.java new file mode 100644 index 0000000000..7f46dd24e9 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/BatchMessageOrBuilder.java @@ -0,0 +1,84 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +@SuppressWarnings({"all"}) +public interface BatchMessageOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.common.protocol.grpc.BatchMessage) + com.google.protobuf.MessageOrBuilder { + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + boolean hasHeader(); + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + RequestHeader getHeader(); + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + RequestHeaderOrBuilder getHeaderOrBuilder(); + + /** + * string producerGroup = 2; + */ + String getProducerGroup(); + /** + * string producerGroup = 2; + */ + com.google.protobuf.ByteString + getProducerGroupBytes(); + + /** + * string topic = 3; + */ + String getTopic(); + /** + * string topic = 3; + */ + com.google.protobuf.ByteString + getTopicBytes(); + + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + java.util.List + getMessageItemList(); + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + BatchMessage.MessageItem getMessageItem(int index); + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + int getMessageItemCount(); + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + java.util.List + getMessageItemOrBuilderList(); + /** + * repeated .eventmesh.common.protocol.grpc.BatchMessage.MessageItem messageItem = 4; + */ + BatchMessage.MessageItemOrBuilder getMessageItemOrBuilder( + int index); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/ConsumerServiceGrpc.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/ConsumerServiceGrpc.java new file mode 100644 index 0000000000..8f55f659d3 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/ConsumerServiceGrpc.java @@ -0,0 +1,445 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.grpc.protos; + +import static io.grpc.MethodDescriptor.generateFullMethodName; +import static io.grpc.stub.ClientCalls.asyncBidiStreamingCall; +import static io.grpc.stub.ClientCalls.asyncUnaryCall; +import static io.grpc.stub.ClientCalls.blockingUnaryCall; +import static io.grpc.stub.ClientCalls.futureUnaryCall; +import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall; +import static io.grpc.stub.ServerCalls.asyncUnaryCall; +import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall; +import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; + +/** + */ +@SuppressWarnings({"all"}) +@javax.annotation.Generated( + value = "by gRPC proto compiler (version 1.42.2)", + comments = "Source: eventmesh-client.proto") +public final class ConsumerServiceGrpc { + + private ConsumerServiceGrpc() {} + + public static final String SERVICE_NAME = "eventmesh.common.protocol.grpc.ConsumerService"; + + // Static method descriptors that strictly reflect the proto. + private static volatile io.grpc.MethodDescriptor getSubscribeMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "subscribe", + requestType = Subscription.class, + responseType = Response.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getSubscribeMethod() { + io.grpc.MethodDescriptor getSubscribeMethod; + if ((getSubscribeMethod = ConsumerServiceGrpc.getSubscribeMethod) == null) { + synchronized (ConsumerServiceGrpc.class) { + if ((getSubscribeMethod = ConsumerServiceGrpc.getSubscribeMethod) == null) { + ConsumerServiceGrpc.getSubscribeMethod = getSubscribeMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName( + "eventmesh.common.protocol.grpc.ConsumerService", "subscribe")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + Subscription.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + Response.getDefaultInstance())) + .setSchemaDescriptor(new ConsumerServiceMethodDescriptorSupplier("subscribe")) + .build(); + } + } + } + return getSubscribeMethod; + } + + private static volatile io.grpc.MethodDescriptor getSubscribeStreamMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "subscribeStream", + requestType = Subscription.class, + responseType = SimpleMessage.class, + methodType = io.grpc.MethodDescriptor.MethodType.BIDI_STREAMING) + public static io.grpc.MethodDescriptor getSubscribeStreamMethod() { + io.grpc.MethodDescriptor getSubscribeStreamMethod; + if ((getSubscribeStreamMethod = ConsumerServiceGrpc.getSubscribeStreamMethod) == null) { + synchronized (ConsumerServiceGrpc.class) { + if ((getSubscribeStreamMethod = ConsumerServiceGrpc.getSubscribeStreamMethod) == null) { + ConsumerServiceGrpc.getSubscribeStreamMethod = getSubscribeStreamMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.BIDI_STREAMING) + .setFullMethodName(generateFullMethodName( + "eventmesh.common.protocol.grpc.ConsumerService", "subscribeStream")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + Subscription.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + SimpleMessage.getDefaultInstance())) + .setSchemaDescriptor(new ConsumerServiceMethodDescriptorSupplier("subscribeStream")) + .build(); + } + } + } + return getSubscribeStreamMethod; + } + + private static volatile io.grpc.MethodDescriptor getUnsubscribeMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "unsubscribe", + requestType = Subscription.class, + responseType = Response.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getUnsubscribeMethod() { + io.grpc.MethodDescriptor getUnsubscribeMethod; + if ((getUnsubscribeMethod = ConsumerServiceGrpc.getUnsubscribeMethod) == null) { + synchronized (ConsumerServiceGrpc.class) { + if ((getUnsubscribeMethod = ConsumerServiceGrpc.getUnsubscribeMethod) == null) { + ConsumerServiceGrpc.getUnsubscribeMethod = getUnsubscribeMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName( + "eventmesh.common.protocol.grpc.ConsumerService", "unsubscribe")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + Subscription.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + Response.getDefaultInstance())) + .setSchemaDescriptor(new ConsumerServiceMethodDescriptorSupplier("unsubscribe")) + .build(); + } + } + } + return getUnsubscribeMethod; + } + + /** + * Creates a new async stub that supports all call types for the service + */ + public static ConsumerServiceStub newStub(io.grpc.Channel channel) { + return new ConsumerServiceStub(channel); + } + + /** + * Creates a new blocking-style stub that supports unary and streaming output calls on the service + */ + public static ConsumerServiceBlockingStub newBlockingStub( + io.grpc.Channel channel) { + return new ConsumerServiceBlockingStub(channel); + } + + /** + * Creates a new ListenableFuture-style stub that supports unary calls on the service + */ + public static ConsumerServiceFutureStub newFutureStub( + io.grpc.Channel channel) { + return new ConsumerServiceFutureStub(channel); + } + + /** + */ + public static abstract class ConsumerServiceImplBase implements io.grpc.BindableService { + + /** + *
+     * The subscribed event will be delivered by invoking the webhook url in the Subscription
+     * 
+ */ + public void subscribe(Subscription request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnimplementedUnaryCall(getSubscribeMethod(), responseObserver); + } + + /** + *
+     *  The subscribed event will be delivered through stream of Message
+     * 
+ */ + public io.grpc.stub.StreamObserver subscribeStream( + io.grpc.stub.StreamObserver responseObserver) { + return asyncUnimplementedStreamingCall(getSubscribeStreamMethod(), responseObserver); + } + + /** + */ + public void unsubscribe(Subscription request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnimplementedUnaryCall(getUnsubscribeMethod(), responseObserver); + } + + @Override public final io.grpc.ServerServiceDefinition bindService() { + return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) + .addMethod( + getSubscribeMethod(), + asyncUnaryCall( + new MethodHandlers< + Subscription, + Response>( + this, METHODID_SUBSCRIBE))) + .addMethod( + getSubscribeStreamMethod(), + asyncBidiStreamingCall( + new MethodHandlers< + Subscription, + SimpleMessage>( + this, METHODID_SUBSCRIBE_STREAM))) + .addMethod( + getUnsubscribeMethod(), + asyncUnaryCall( + new MethodHandlers< + Subscription, + Response>( + this, METHODID_UNSUBSCRIBE))) + .build(); + } + } + + /** + */ + public static final class ConsumerServiceStub extends io.grpc.stub.AbstractStub { + private ConsumerServiceStub(io.grpc.Channel channel) { + super(channel); + } + + private ConsumerServiceStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected ConsumerServiceStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new ConsumerServiceStub(channel, callOptions); + } + + /** + *
+     * The subscribed event will be delivered by invoking the webhook url in the Subscription
+     * 
+ */ + public void subscribe(Subscription request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + getChannel().newCall(getSubscribeMethod(), getCallOptions()), request, responseObserver); + } + + /** + *
+     *  The subscribed event will be delivered through stream of Message
+     * 
+ */ + public io.grpc.stub.StreamObserver subscribeStream( + io.grpc.stub.StreamObserver responseObserver) { + return asyncBidiStreamingCall( + getChannel().newCall(getSubscribeStreamMethod(), getCallOptions()), responseObserver); + } + + /** + */ + public void unsubscribe(Subscription request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + getChannel().newCall(getUnsubscribeMethod(), getCallOptions()), request, responseObserver); + } + } + + /** + */ + public static final class ConsumerServiceBlockingStub extends io.grpc.stub.AbstractStub { + private ConsumerServiceBlockingStub(io.grpc.Channel channel) { + super(channel); + } + + private ConsumerServiceBlockingStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected ConsumerServiceBlockingStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new ConsumerServiceBlockingStub(channel, callOptions); + } + + /** + *
+     * The subscribed event will be delivered by invoking the webhook url in the Subscription
+     * 
+ */ + public Response subscribe(Subscription request) { + return blockingUnaryCall( + getChannel(), getSubscribeMethod(), getCallOptions(), request); + } + + /** + */ + public Response unsubscribe(Subscription request) { + return blockingUnaryCall( + getChannel(), getUnsubscribeMethod(), getCallOptions(), request); + } + } + + /** + */ + public static final class ConsumerServiceFutureStub extends io.grpc.stub.AbstractStub { + private ConsumerServiceFutureStub(io.grpc.Channel channel) { + super(channel); + } + + private ConsumerServiceFutureStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected ConsumerServiceFutureStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new ConsumerServiceFutureStub(channel, callOptions); + } + + /** + *
+     * The subscribed event will be delivered by invoking the webhook url in the Subscription
+     * 
+ */ + public com.google.common.util.concurrent.ListenableFuture subscribe( + Subscription request) { + return futureUnaryCall( + getChannel().newCall(getSubscribeMethod(), getCallOptions()), request); + } + + /** + */ + public com.google.common.util.concurrent.ListenableFuture unsubscribe( + Subscription request) { + return futureUnaryCall( + getChannel().newCall(getUnsubscribeMethod(), getCallOptions()), request); + } + } + + private static final int METHODID_SUBSCRIBE = 0; + private static final int METHODID_UNSUBSCRIBE = 1; + private static final int METHODID_SUBSCRIBE_STREAM = 2; + + private static final class MethodHandlers implements + io.grpc.stub.ServerCalls.UnaryMethod, + io.grpc.stub.ServerCalls.ServerStreamingMethod, + io.grpc.stub.ServerCalls.ClientStreamingMethod, + io.grpc.stub.ServerCalls.BidiStreamingMethod { + private final ConsumerServiceImplBase serviceImpl; + private final int methodId; + + MethodHandlers(ConsumerServiceImplBase serviceImpl, int methodId) { + this.serviceImpl = serviceImpl; + this.methodId = methodId; + } + + @Override + @SuppressWarnings("unchecked") + public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + case METHODID_SUBSCRIBE: + serviceImpl.subscribe((Subscription) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_UNSUBSCRIBE: + serviceImpl.unsubscribe((Subscription) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + default: + throw new AssertionError(); + } + } + + @Override + @SuppressWarnings("unchecked") + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + case METHODID_SUBSCRIBE_STREAM: + return (io.grpc.stub.StreamObserver) serviceImpl.subscribeStream( + (io.grpc.stub.StreamObserver) responseObserver); + default: + throw new AssertionError(); + } + } + } + + private static abstract class ConsumerServiceBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier { + ConsumerServiceBaseDescriptorSupplier() {} + + @Override + public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { + return EventmeshGrpc.getDescriptor(); + } + + @Override + public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() { + return getFileDescriptor().findServiceByName("ConsumerService"); + } + } + + private static final class ConsumerServiceFileDescriptorSupplier + extends ConsumerServiceBaseDescriptorSupplier { + ConsumerServiceFileDescriptorSupplier() {} + } + + private static final class ConsumerServiceMethodDescriptorSupplier + extends ConsumerServiceBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoMethodDescriptorSupplier { + private final String methodName; + + ConsumerServiceMethodDescriptorSupplier(String methodName) { + this.methodName = methodName; + } + + @Override + public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() { + return getServiceDescriptor().findMethodByName(methodName); + } + } + + private static volatile io.grpc.ServiceDescriptor serviceDescriptor; + + public static io.grpc.ServiceDescriptor getServiceDescriptor() { + io.grpc.ServiceDescriptor result = serviceDescriptor; + if (result == null) { + synchronized (ConsumerServiceGrpc.class) { + result = serviceDescriptor; + if (result == null) { + serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) + .setSchemaDescriptor(new ConsumerServiceFileDescriptorSupplier()) + .addMethod(getSubscribeMethod()) + .addMethod(getSubscribeStreamMethod()) + .addMethod(getUnsubscribeMethod()) + .build(); + } + } + } + return result; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/EventmeshGrpc.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/EventmeshGrpc.java new file mode 100644 index 0000000000..4a1f2de63f --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/EventmeshGrpc.java @@ -0,0 +1,283 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +@SuppressWarnings({"all"}) +public final class EventmeshGrpc { + private EventmeshGrpc() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_RequestHeader_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_RequestHeader_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_SimpleMessage_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_SimpleMessage_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_SimpleMessage_PropertiesEntry_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_SimpleMessage_PropertiesEntry_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_BatchMessage_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_BatchMessage_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_PropertiesEntry_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_PropertiesEntry_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_Response_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_Response_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_Subscription_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_Subscription_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_Subscription_SubscriptionItem_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_Subscription_SubscriptionItem_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_PropertiesEntry_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_PropertiesEntry_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_Heartbeat_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_Heartbeat_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_common_protocol_grpc_Heartbeat_HeartbeatItem_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_common_protocol_grpc_Heartbeat_HeartbeatItem_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + String[] descriptorData = { + "\n\026eventmesh-client.proto\022\036eventmesh.comm" + + "on.protocol.grpc\"\332\001\n\rRequestHeader\022\013\n\003en" + + "v\030\001 \001(\t\022\016\n\006region\030\002 \001(\t\022\013\n\003idc\030\003 \001(\t\022\n\n\002" + + "ip\030\004 \001(\t\022\013\n\003pid\030\005 \001(\t\022\013\n\003sys\030\006 \001(\t\022\020\n\010us" + + "ername\030\007 \001(\t\022\020\n\010password\030\010 \001(\t\022\020\n\010langua" + + "ge\030\t \001(\t\022\024\n\014protocolType\030\n \001(\t\022\027\n\017protoc" + + "olVersion\030\013 \001(\t\022\024\n\014protocolDesc\030\014 \001(\t\"\307\002" + + "\n\rSimpleMessage\022=\n\006header\030\001 \001(\0132-.eventm" + + "esh.common.protocol.grpc.RequestHeader\022\025" + + "\n\rproducerGroup\030\002 \001(\t\022\r\n\005topic\030\003 \001(\t\022\017\n\007" + + "content\030\004 \001(\t\022\013\n\003ttl\030\005 \001(\t\022\020\n\010uniqueId\030\006" + + " \001(\t\022\016\n\006seqNum\030\007 \001(\t\022\013\n\003tag\030\010 \001(\t\022Q\n\npro" + + "perties\030\t \003(\0132=.eventmesh.common.protoco" + + "l.grpc.SimpleMessage.PropertiesEntry\0321\n\017" + + "PropertiesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 " + + "\001(\t:\0028\001\"\260\003\n\014BatchMessage\022=\n\006header\030\001 \001(\013" + + "2-.eventmesh.common.protocol.grpc.Reques" + + "tHeader\022\025\n\rproducerGroup\030\002 \001(\t\022\r\n\005topic\030" + + "\003 \001(\t\022M\n\013messageItem\030\004 \003(\01328.eventmesh.c" + + "ommon.protocol.grpc.BatchMessage.Message" + + "Item\032\353\001\n\013MessageItem\022\017\n\007content\030\001 \001(\t\022\013\n" + + "\003ttl\030\002 \001(\t\022\020\n\010uniqueId\030\003 \001(\t\022\016\n\006seqNum\030\004" + + " \001(\t\022\013\n\003tag\030\005 \001(\t\022\\\n\nproperties\030\006 \003(\0132H." + + "eventmesh.common.protocol.grpc.BatchMess" + + "age.MessageItem.PropertiesEntry\0321\n\017Prope" + + "rtiesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\002" + + "8\001\"?\n\010Response\022\020\n\010respCode\030\001 \001(\t\022\017\n\007resp" + + "Msg\030\002 \001(\t\022\020\n\010respTime\030\003 \001(\t\"\325\006\n\014Subscrip" + + "tion\022=\n\006header\030\001 \001(\0132-.eventmesh.common." + + "protocol.grpc.RequestHeader\022\025\n\rconsumerG" + + "roup\030\002 \001(\t\022X\n\021subscriptionItems\030\003 \003(\0132=." + + "eventmesh.common.protocol.grpc.Subscript" + + "ion.SubscriptionItem\022\013\n\003url\030\004 \001(\t\022A\n\005rep" + + "ly\030\005 \001(\01322.eventmesh.common.protocol.grp" + + "c.Subscription.Reply\032\274\002\n\020SubscriptionIte" + + "m\022\r\n\005topic\030\001 \001(\t\022\\\n\004mode\030\002 \001(\0162N.eventme" + + "sh.common.protocol.grpc.Subscription.Sub" + + "scriptionItem.SubscriptionMode\022\\\n\004type\030\003" + + " \001(\0162N.eventmesh.common.protocol.grpc.Su" + + "bscription.SubscriptionItem.Subscription" + + "Type\"4\n\020SubscriptionMode\022\016\n\nCLUSTERING\020\000" + + "\022\020\n\014BROADCASTING\020\001\"\'\n\020SubscriptionType\022\t" + + "\n\005ASYNC\020\000\022\010\n\004SYNC\020\001\032\205\002\n\005Reply\022\025\n\rproduce" + + "rGroup\030\001 \001(\t\022\r\n\005topic\030\002 \001(\t\022\017\n\007content\030\003" + + " \001(\t\022\013\n\003ttl\030\004 \001(\t\022\020\n\010uniqueId\030\005 \001(\t\022\016\n\006s" + + "eqNum\030\006 \001(\t\022\013\n\003tag\030\007 \001(\t\022V\n\nproperties\030\010" + + " \003(\0132B.eventmesh.common.protocol.grpc.Su" + + "bscription.Reply.PropertiesEntry\0321\n\017Prop" + + "ertiesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:" + + "\0028\001\"\340\002\n\tHeartbeat\022=\n\006header\030\001 \001(\0132-.even" + + "tmesh.common.protocol.grpc.RequestHeader" + + "\022H\n\nclientType\030\002 \001(\01624.eventmesh.common." + + "protocol.grpc.Heartbeat.ClientType\022\025\n\rpr" + + "oducerGroup\030\003 \001(\t\022\025\n\rconsumerGroup\030\004 \001(\t" + + "\022O\n\016heartbeatItems\030\005 \003(\01327.eventmesh.com" + + "mon.protocol.grpc.Heartbeat.HeartbeatIte" + + "m\032+\n\rHeartbeatItem\022\r\n\005topic\030\001 \001(\t\022\013\n\003url" + + "\030\002 \001(\t\"\036\n\nClientType\022\007\n\003PUB\020\000\022\007\n\003SUB\020\0012\314" + + "\002\n\020PublisherService\022b\n\007publish\022-.eventme" + + "sh.common.protocol.grpc.SimpleMessage\032(." + + "eventmesh.common.protocol.grpc.Response\022" + + "l\n\014requestReply\022-.eventmesh.common.proto" + + "col.grpc.SimpleMessage\032-.eventmesh.commo" + + "n.protocol.grpc.SimpleMessage\022f\n\014batchPu" + + "blish\022,.eventmesh.common.protocol.grpc.B" + + "atchMessage\032(.eventmesh.common.protocol." + + "grpc.Response2\321\002\n\017ConsumerService\022c\n\tsub" + + "scribe\022,.eventmesh.common.protocol.grpc." + + "Subscription\032(.eventmesh.common.protocol" + + ".grpc.Response\022r\n\017subscribeStream\022,.even" + + "tmesh.common.protocol.grpc.Subscription\032" + + "-.eventmesh.common.protocol.grpc.SimpleM" + + "essage(\0010\001\022e\n\013unsubscribe\022,.eventmesh.co" + + "mmon.protocol.grpc.Subscription\032(.eventm" + + "esh.common.protocol.grpc.Response2t\n\020Hea" + + "rtbeatService\022`\n\theartbeat\022).eventmesh.c" + + "ommon.protocol.grpc.Heartbeat\032(.eventmes" + + "h.common.protocol.grpc.ResponseBC\n0org.a" + + "pache.eventmesh.common.protocol.grpc.pro" + + "tosB\rEventmeshGrpcP\001b\006proto3" + }; + com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = + new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { + public com.google.protobuf.ExtensionRegistry assignDescriptors( + com.google.protobuf.Descriptors.FileDescriptor root) { + descriptor = root; + return null; + } + }; + com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }, assigner); + internal_static_eventmesh_common_protocol_grpc_RequestHeader_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_eventmesh_common_protocol_grpc_RequestHeader_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_RequestHeader_descriptor, + new String[] { "Env", "Region", "Idc", "Ip", "Pid", "Sys", "Username", "Password", "Language", "ProtocolType", "ProtocolVersion", "ProtocolDesc", }); + internal_static_eventmesh_common_protocol_grpc_SimpleMessage_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_eventmesh_common_protocol_grpc_SimpleMessage_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_SimpleMessage_descriptor, + new String[] { "Header", "ProducerGroup", "Topic", "Content", "Ttl", "UniqueId", "SeqNum", "Tag", "Properties", }); + internal_static_eventmesh_common_protocol_grpc_SimpleMessage_PropertiesEntry_descriptor = + internal_static_eventmesh_common_protocol_grpc_SimpleMessage_descriptor.getNestedTypes().get(0); + internal_static_eventmesh_common_protocol_grpc_SimpleMessage_PropertiesEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_SimpleMessage_PropertiesEntry_descriptor, + new String[] { "Key", "Value", }); + internal_static_eventmesh_common_protocol_grpc_BatchMessage_descriptor = + getDescriptor().getMessageTypes().get(2); + internal_static_eventmesh_common_protocol_grpc_BatchMessage_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_BatchMessage_descriptor, + new String[] { "Header", "ProducerGroup", "Topic", "MessageItem", }); + internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_descriptor = + internal_static_eventmesh_common_protocol_grpc_BatchMessage_descriptor.getNestedTypes().get(0); + internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_descriptor, + new String[] { "Content", "Ttl", "UniqueId", "SeqNum", "Tag", "Properties", }); + internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_PropertiesEntry_descriptor = + internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_descriptor.getNestedTypes().get(0); + internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_PropertiesEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_BatchMessage_MessageItem_PropertiesEntry_descriptor, + new String[] { "Key", "Value", }); + internal_static_eventmesh_common_protocol_grpc_Response_descriptor = + getDescriptor().getMessageTypes().get(3); + internal_static_eventmesh_common_protocol_grpc_Response_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_Response_descriptor, + new String[] { "RespCode", "RespMsg", "RespTime", }); + internal_static_eventmesh_common_protocol_grpc_Subscription_descriptor = + getDescriptor().getMessageTypes().get(4); + internal_static_eventmesh_common_protocol_grpc_Subscription_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_Subscription_descriptor, + new String[] { "Header", "ConsumerGroup", "SubscriptionItems", "Url", "Reply", }); + internal_static_eventmesh_common_protocol_grpc_Subscription_SubscriptionItem_descriptor = + internal_static_eventmesh_common_protocol_grpc_Subscription_descriptor.getNestedTypes().get(0); + internal_static_eventmesh_common_protocol_grpc_Subscription_SubscriptionItem_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_Subscription_SubscriptionItem_descriptor, + new String[] { "Topic", "Mode", "Type", }); + internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_descriptor = + internal_static_eventmesh_common_protocol_grpc_Subscription_descriptor.getNestedTypes().get(1); + internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_descriptor, + new String[] { "ProducerGroup", "Topic", "Content", "Ttl", "UniqueId", "SeqNum", "Tag", "Properties", }); + internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_PropertiesEntry_descriptor = + internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_descriptor.getNestedTypes().get(0); + internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_PropertiesEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_PropertiesEntry_descriptor, + new String[] { "Key", "Value", }); + internal_static_eventmesh_common_protocol_grpc_Heartbeat_descriptor = + getDescriptor().getMessageTypes().get(5); + internal_static_eventmesh_common_protocol_grpc_Heartbeat_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_Heartbeat_descriptor, + new String[] { "Header", "ClientType", "ProducerGroup", "ConsumerGroup", "HeartbeatItems", }); + internal_static_eventmesh_common_protocol_grpc_Heartbeat_HeartbeatItem_descriptor = + internal_static_eventmesh_common_protocol_grpc_Heartbeat_descriptor.getNestedTypes().get(0); + internal_static_eventmesh_common_protocol_grpc_Heartbeat_HeartbeatItem_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_common_protocol_grpc_Heartbeat_HeartbeatItem_descriptor, + new String[] { "Topic", "Url", }); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/Heartbeat.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/Heartbeat.java new file mode 100644 index 0000000000..54b68ee467 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/Heartbeat.java @@ -0,0 +1,1988 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +import java.util.Objects; + +import com.google.protobuf.ByteString; + + + +/** + * Protobuf type {@code eventmesh.common.protocol.grpc.Heartbeat} + */ +@SuppressWarnings({"all"}) +public final class Heartbeat extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.common.protocol.grpc.Heartbeat) + HeartbeatOrBuilder { + private static final long serialVersionUID = -617903330545075556L; + + // Use Heartbeat.newBuilder() to construct. + private Heartbeat(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private Heartbeat() { + clientType_ = 0; + producerGroup_ = ""; + consumerGroup_ = ""; + heartbeatItems_ = java.util.Collections.emptyList(); + } + + @Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + + private Heartbeat( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownFieldProto3( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + RequestHeader.Builder subBuilder = null; + if (header_ != null) { + subBuilder = header_.toBuilder(); + } + header_ = input.readMessage(RequestHeader.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(header_); + header_ = subBuilder.buildPartial(); + } + + break; + } + case 16: { + clientType_ = input.readEnum(); + break; + } + case 26: { + producerGroup_ = input.readStringRequireUtf8(); + break; + } + case 34: { + consumerGroup_ = input.readStringRequireUtf8(); + break; + } + case 42: { + if (!((mutable_bitField0_ & 0x00000010) == 0x00000010)) { + heartbeatItems_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000010; + } + heartbeatItems_.add( + input.readMessage(HeartbeatItem.parser(), extensionRegistry)); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000010) == 0x00000010)) { + heartbeatItems_ = java.util.Collections.unmodifiableList(heartbeatItems_); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Heartbeat_descriptor; + } + + protected FieldAccessorTable internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Heartbeat_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Heartbeat.class, Builder.class); + } + + /** + * Protobuf enum {@code eventmesh.common.protocol.grpc.Heartbeat.ClientType} + */ + public enum ClientType + implements com.google.protobuf.ProtocolMessageEnum { + /** + * PUB = 0; + */ + PUB(0), + /** + * SUB = 1; + */ + SUB(1), + UNRECOGNIZED(-1), + ; + + /** + * PUB = 0; + */ + public static final int PUB_VALUE = 0; + /** + * SUB = 1; + */ + public static final int SUB_VALUE = 1; + + + public final int getNumber() { + if (this == UNRECOGNIZED) { + throw new IllegalArgumentException( + "Can't get the number of an unknown enum value."); + } + return value; + } + + /** + * @deprecated Use {@link #forNumber(int)} instead. + */ + @Deprecated + public static ClientType valueOf(int value) { + return forNumber(value); + } + + public static ClientType forNumber(int value) { + switch (value) { + case 0: + return PUB; + case 1: + return SUB; + default: + return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + + private static final com.google.protobuf.Internal.EnumLiteMap< + ClientType> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public ClientType findValueByNumber(int number) { + return ClientType.forNumber(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + return getDescriptor().getValues().get(ordinal()); + } + + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return Heartbeat.getDescriptor().getEnumTypes().get(0); + } + + private static final ClientType[] VALUES = values(); + + public static ClientType valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + if (desc.getIndex() == -1) { + return UNRECOGNIZED; + } + return VALUES[desc.getIndex()]; + } + + private final int value; + + private ClientType(int value) { + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:eventmesh.common.protocol.grpc.Heartbeat.ClientType) + } + + public interface HeartbeatItemOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem) + com.google.protobuf.MessageOrBuilder { + + /** + * string topic = 1; + */ + String getTopic(); + + /** + * string topic = 1; + */ + com.google.protobuf.ByteString + getTopicBytes(); + + /** + * string url = 2; + */ + String getUrl(); + + /** + * string url = 2; + */ + com.google.protobuf.ByteString + getUrlBytes(); + } + + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem} + */ + public static final class HeartbeatItem extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem) + HeartbeatItemOrBuilder { + private static final long serialVersionUID = 0L; + + // Use HeartbeatItem.newBuilder() to construct. + private HeartbeatItem(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private HeartbeatItem() { + topic_ = ""; + url_ = ""; + } + + @Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + + private HeartbeatItem( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownFieldProto3( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + topic_ = input.readStringRequireUtf8(); + break; + } + case 18: { + url_ = input.readStringRequireUtf8(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Heartbeat_HeartbeatItem_descriptor; + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Heartbeat_HeartbeatItem_fieldAccessorTable + .ensureFieldAccessorsInitialized( + HeartbeatItem.class, Builder.class); + } + + public static final int TOPIC_FIELD_NUMBER = 1; + private volatile String topic_; + + /** + * string topic = 1; + */ + public String getTopic() { + return topic_; + } + + /** + * string topic = 1; + */ + public com.google.protobuf.ByteString getTopicBytes() { + return ByteString.copyFromUtf8(topic_); + } + + public static final int URL_FIELD_NUMBER = 2; + private volatile String url_; + + /** + * string url = 2; + */ + public String getUrl() { + return url_; + } + + /** + * string url = 2; + */ + public com.google.protobuf.ByteString getUrlBytes() { + return ByteString.copyFromUtf8(url_); + } + + private byte memoizedIsInitialized = -1; + + public final boolean isInitialized() { + if (memoizedIsInitialized == 1) return true; + if (memoizedIsInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getTopicBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, topic_); + } + if (!getUrlBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, url_); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getTopicBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, topic_); + } + if (!getUrlBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, url_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof HeartbeatItem)) { + return super.equals(obj); + } + HeartbeatItem other = (HeartbeatItem) obj; + + return getTopic().equals(other.getTopic()) + && getUrl().equals(other.getUrl()) + && unknownFields.equals(other.unknownFields); + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + TOPIC_FIELD_NUMBER; + hash = (53 * hash) + getTopic().hashCode(); + hash = (37 * hash) + URL_FIELD_NUMBER; + hash = (53 * hash) + getUrl().hashCode(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static HeartbeatItem parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static HeartbeatItem parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static HeartbeatItem parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static HeartbeatItem parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static HeartbeatItem parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static HeartbeatItem parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static HeartbeatItem parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static HeartbeatItem parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static HeartbeatItem parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static HeartbeatItem parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static HeartbeatItem parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static HeartbeatItem parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(HeartbeatItem prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + return new Builder(parent); + } + + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem) + HeartbeatItemOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Heartbeat_HeartbeatItem_descriptor; + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Heartbeat_HeartbeatItem_fieldAccessorTable + .ensureFieldAccessorsInitialized( + HeartbeatItem.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.grpc.protos.Heartbeat.HeartbeatItem.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + + public Builder clear() { + super.clear(); + topic_ = ""; + url_ = ""; + + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Heartbeat_HeartbeatItem_descriptor; + } + + public HeartbeatItem getDefaultInstanceForType() { + return HeartbeatItem.getDefaultInstance(); + } + + public HeartbeatItem build() { + HeartbeatItem result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public HeartbeatItem buildPartial() { + HeartbeatItem result = new HeartbeatItem(this); + result.topic_ = topic_; + result.url_ = url_; + onBuilt(); + return result; + } + + public Builder clone() { + return (Builder) super.clone(); + } + + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.setField(field, value); + } + + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return (Builder) super.clearField(field); + } + + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return (Builder) super.clearOneof(oneof); + } + + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return (Builder) super.setRepeatedField(field, index, value); + } + + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.addRepeatedField(field, value); + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof HeartbeatItem) { + return mergeFrom((HeartbeatItem) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(HeartbeatItem other) { + if (other == HeartbeatItem.getDefaultInstance()) return this; + if (!other.getTopic().isEmpty()) { + topic_ = other.topic_; + onChanged(); + } + if (!other.getUrl().isEmpty()) { + url_ = other.url_; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + HeartbeatItem parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (HeartbeatItem) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private String topic_ = ""; + + /** + * string topic = 1; + */ + public String getTopic() { + return topic_; + } + + /** + * string topic = 1; + */ + public com.google.protobuf.ByteString getTopicBytes() { + return ByteString.copyFromUtf8(topic_); + } + + /** + * string topic = 1; + */ + public Builder setTopic( + String value) { + Objects.requireNonNull(value, "topic can not be null"); + + topic_ = value; + onChanged(); + return this; + } + + /** + * string topic = 1; + */ + public Builder clearTopic() { + + topic_ = getDefaultInstance().getTopic(); + onChanged(); + return this; + } + + /** + * string topic = 1; + */ + public Builder setTopicBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "TopicBytes can not be null"); + + checkByteStringIsUtf8(value); + + topic_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String url_ = ""; + + /** + * string url = 2; + */ + public String getUrl() { + return url_; + } + + /** + * string url = 2; + */ + public com.google.protobuf.ByteString getUrlBytes() { + return ByteString.copyFromUtf8(url_); + } + + /** + * string url = 2; + */ + public Builder setUrl( + String value) { + Objects.requireNonNull(value, "url can not be null"); + + url_ = value; + onChanged(); + return this; + } + + /** + * string url = 2; + */ + public Builder clearUrl() { + + url_ = getDefaultInstance().getUrl(); + onChanged(); + return this; + } + + /** + * string url = 2; + */ + public Builder setUrlBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "UrlBytes can not be null"); + checkByteStringIsUtf8(value); + + url_ = value.toStringUtf8(); + onChanged(); + return this; + } + + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFieldsProto3(unknownFields); + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem) + } + + // @@protoc_insertion_point(class_scope:eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem) + private static final HeartbeatItem DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new HeartbeatItem(); + } + + public static HeartbeatItem getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public HeartbeatItem parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new HeartbeatItem(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public HeartbeatItem getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private int bitField0_; + public static final int HEADER_FIELD_NUMBER = 1; + private RequestHeader header_; + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public boolean hasHeader() { + return header_ != null; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeader getHeader() { + return header_ == null ? RequestHeader.getDefaultInstance() : header_; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeaderOrBuilder getHeaderOrBuilder() { + return getHeader(); + } + + public static final int CLIENTTYPE_FIELD_NUMBER = 2; + private int clientType_; + + /** + * .eventmesh.common.protocol.grpc.Heartbeat.ClientType clientType = 2; + */ + public int getClientTypeValue() { + return clientType_; + } + + /** + * .eventmesh.common.protocol.grpc.Heartbeat.ClientType clientType = 2; + */ + public ClientType getClientType() { + ClientType result = ClientType.valueOf(clientType_); + return result == null ? ClientType.UNRECOGNIZED : result; + } + + public static final int PRODUCERGROUP_FIELD_NUMBER = 3; + private volatile String producerGroup_; + + /** + * string producerGroup = 3; + */ + public String getProducerGroup() { + return producerGroup_; + } + + /** + * string producerGroup = 3; + */ + public com.google.protobuf.ByteString + getProducerGroupBytes() { + return ByteString.copyFromUtf8(producerGroup_); + } + + public static final int CONSUMERGROUP_FIELD_NUMBER = 4; + private volatile String consumerGroup_; + + /** + * string consumerGroup = 4; + */ + public String getConsumerGroup() { + return consumerGroup_; + } + + /** + * string consumerGroup = 4; + */ + public com.google.protobuf.ByteString + getConsumerGroupBytes() { + return ByteString.copyFromUtf8(consumerGroup_); + } + + public static final int HEARTBEATITEMS_FIELD_NUMBER = 5; + private java.util.List heartbeatItems_; + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public java.util.List getHeartbeatItemsList() { + return heartbeatItems_; + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public java.util.List + getHeartbeatItemsOrBuilderList() { + return heartbeatItems_; + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public int getHeartbeatItemsCount() { + return heartbeatItems_.size(); + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public HeartbeatItem getHeartbeatItems(int index) { + return heartbeatItems_.get(index); + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public HeartbeatItemOrBuilder getHeartbeatItemsOrBuilder( + int index) { + return heartbeatItems_.get(index); + } + + private byte memoizedIsInitialized = -1; + + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (header_ != null) { + output.writeMessage(1, getHeader()); + } + if (clientType_ != ClientType.PUB.getNumber()) { + output.writeEnum(2, clientType_); + } + if (!getProducerGroupBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, producerGroup_); + } + if (!getConsumerGroupBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 4, consumerGroup_); + } + for (HeartbeatItem heartbeatItem : heartbeatItems_) { + output.writeMessage(5, heartbeatItem); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (header_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, getHeader()); + } + if (clientType_ != ClientType.PUB.getNumber()) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(2, clientType_); + } + if (!getProducerGroupBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, producerGroup_); + } + if (!getConsumerGroupBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, consumerGroup_); + } + for (HeartbeatItem heartbeatItem : heartbeatItems_) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, heartbeatItem); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Heartbeat)) { + return super.equals(obj); + } + Heartbeat other = (Heartbeat) obj; + + return hasHeader() == other.hasHeader() + && hasHeader() ? getHeader().equals(other.getHeader()) : true + && clientType_ == other.clientType_ + && getProducerGroup().equals(other.getProducerGroup()) + && getConsumerGroup().equals(other.getConsumerGroup()) + && getHeartbeatItemsList().equals(other.getHeartbeatItemsList()) + && unknownFields.equals(other.unknownFields); + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasHeader()) { + hash = (37 * hash) + HEADER_FIELD_NUMBER; + hash = (53 * hash) + getHeader().hashCode(); + } + hash = (37 * hash) + CLIENTTYPE_FIELD_NUMBER; + hash = (53 * hash) + clientType_; + hash = (37 * hash) + PRODUCERGROUP_FIELD_NUMBER; + hash = (53 * hash) + getProducerGroup().hashCode(); + hash = (37 * hash) + CONSUMERGROUP_FIELD_NUMBER; + hash = (53 * hash) + getConsumerGroup().hashCode(); + if (getHeartbeatItemsCount() > 0) { + hash = (37 * hash) + HEARTBEATITEMS_FIELD_NUMBER; + hash = (53 * hash) + getHeartbeatItemsList().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static Heartbeat parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static Heartbeat parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static Heartbeat parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static Heartbeat parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static Heartbeat parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static Heartbeat parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static Heartbeat parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static Heartbeat parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static Heartbeat parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static Heartbeat parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static Heartbeat parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static Heartbeat parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(Heartbeat prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + return new Builder(parent); + } + + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.Heartbeat} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.common.protocol.grpc.Heartbeat) + HeartbeatOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Heartbeat_descriptor; + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Heartbeat_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Heartbeat.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.grpc.protos.Heartbeat.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getHeartbeatItemsFieldBuilder(); + } + } + + public Builder clear() { + super.clear(); + if (headerBuilder_ == null) { + header_ = null; + } else { + header_ = null; + headerBuilder_ = null; + } + clientType_ = 0; + + producerGroup_ = ""; + + consumerGroup_ = ""; + + if (heartbeatItemsBuilder_ == null) { + heartbeatItems_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000010); + } else { + heartbeatItemsBuilder_.clear(); + } + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Heartbeat_descriptor; + } + + public Heartbeat getDefaultInstanceForType() { + return Heartbeat.getDefaultInstance(); + } + + public Heartbeat build() { + Heartbeat result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public Heartbeat buildPartial() { + Heartbeat result = new Heartbeat(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (headerBuilder_ == null) { + result.header_ = header_; + } else { + result.header_ = headerBuilder_.build(); + } + result.clientType_ = clientType_; + result.producerGroup_ = producerGroup_; + result.consumerGroup_ = consumerGroup_; + if (heartbeatItemsBuilder_ == null) { + if (((bitField0_ & 0x00000010) == 0x00000010)) { + heartbeatItems_ = java.util.Collections.unmodifiableList(heartbeatItems_); + bitField0_ = (bitField0_ & ~0x00000010); + } + result.heartbeatItems_ = heartbeatItems_; + } else { + result.heartbeatItems_ = heartbeatItemsBuilder_.build(); + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder clone() { + return (Builder) super.clone(); + } + + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.setField(field, value); + } + + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return (Builder) super.clearField(field); + } + + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return (Builder) super.clearOneof(oneof); + } + + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return (Builder) super.setRepeatedField(field, index, value); + } + + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.addRepeatedField(field, value); + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof Heartbeat) { + return mergeFrom((Heartbeat) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(Heartbeat other) { + if (other == Heartbeat.getDefaultInstance()) return this; + if (other.hasHeader()) { + mergeHeader(other.getHeader()); + } + if (other.clientType_ != 0) { + setClientTypeValue(other.getClientTypeValue()); + } + if (!other.getProducerGroup().isEmpty()) { + producerGroup_ = other.producerGroup_; + onChanged(); + } + if (!other.getConsumerGroup().isEmpty()) { + consumerGroup_ = other.consumerGroup_; + onChanged(); + } + if (heartbeatItemsBuilder_ == null) { + if (!other.heartbeatItems_.isEmpty()) { + if (heartbeatItems_.isEmpty()) { + heartbeatItems_ = other.heartbeatItems_; + bitField0_ = (bitField0_ & ~0x00000010); + } else { + ensureHeartbeatItemsIsMutable(); + heartbeatItems_.addAll(other.heartbeatItems_); + } + onChanged(); + } + } else { + if (!other.heartbeatItems_.isEmpty()) { + if (heartbeatItemsBuilder_.isEmpty()) { + heartbeatItemsBuilder_.dispose(); + heartbeatItemsBuilder_ = null; + heartbeatItems_ = other.heartbeatItems_; + bitField0_ = (bitField0_ & ~0x00000010); + heartbeatItemsBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getHeartbeatItemsFieldBuilder() : null; + } else { + heartbeatItemsBuilder_.addAllMessages(other.heartbeatItems_); + } + } + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Heartbeat parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (Heartbeat) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private int bitField0_; + + private RequestHeader header_ = null; + private com.google.protobuf.SingleFieldBuilderV3< + RequestHeader, RequestHeader.Builder, RequestHeaderOrBuilder> headerBuilder_; + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public boolean hasHeader() { + return headerBuilder_ != null || header_ != null; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeader getHeader() { + if (headerBuilder_ == null) { + return header_ == null ? RequestHeader.getDefaultInstance() : header_; + } else { + return headerBuilder_.getMessage(); + } + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder setHeader(RequestHeader value) { + if (headerBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + header_ = value; + onChanged(); + } else { + headerBuilder_.setMessage(value); + } + + return this; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder setHeader( + RequestHeader.Builder builderForValue) { + if (headerBuilder_ == null) { + header_ = builderForValue.build(); + onChanged(); + } else { + headerBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder mergeHeader(RequestHeader value) { + if (headerBuilder_ == null) { + if (header_ != null) { + header_ = + RequestHeader.newBuilder(header_).mergeFrom(value).buildPartial(); + } else { + header_ = value; + } + onChanged(); + } else { + headerBuilder_.mergeFrom(value); + } + + return this; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder clearHeader() { + if (headerBuilder_ == null) { + header_ = null; + onChanged(); + } else { + header_ = null; + headerBuilder_ = null; + } + + return this; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeader.Builder getHeaderBuilder() { + + onChanged(); + return getHeaderFieldBuilder().getBuilder(); + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeaderOrBuilder getHeaderOrBuilder() { + if (headerBuilder_ != null) { + return headerBuilder_.getMessageOrBuilder(); + } else { + return header_ == null ? + RequestHeader.getDefaultInstance() : header_; + } + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + private com.google.protobuf.SingleFieldBuilderV3< + RequestHeader, RequestHeader.Builder, RequestHeaderOrBuilder> + getHeaderFieldBuilder() { + if (headerBuilder_ == null) { + headerBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + RequestHeader, RequestHeader.Builder, RequestHeaderOrBuilder>( + getHeader(), + getParentForChildren(), + isClean()); + header_ = null; + } + return headerBuilder_; + } + + private int clientType_ = 0; + + /** + * .eventmesh.common.protocol.grpc.Heartbeat.ClientType clientType = 2; + */ + public int getClientTypeValue() { + return clientType_; + } + + /** + * .eventmesh.common.protocol.grpc.Heartbeat.ClientType clientType = 2; + */ + public Builder setClientTypeValue(int value) { + clientType_ = value; + onChanged(); + return this; + } + + /** + * .eventmesh.common.protocol.grpc.Heartbeat.ClientType clientType = 2; + */ + public ClientType getClientType() { + ClientType result = ClientType.valueOf(clientType_); + return result == null ? ClientType.UNRECOGNIZED : result; + } + + /** + * .eventmesh.common.protocol.grpc.Heartbeat.ClientType clientType = 2; + */ + public Builder setClientType(ClientType value) { + if (value == null) { + throw new NullPointerException(); + } + + clientType_ = value.getNumber(); + onChanged(); + return this; + } + + /** + * .eventmesh.common.protocol.grpc.Heartbeat.ClientType clientType = 2; + */ + public Builder clearClientType() { + + clientType_ = 0; + onChanged(); + return this; + } + + private String producerGroup_ = ""; + + /** + * string producerGroup = 3; + */ + public String getProducerGroup() { + return producerGroup_; + } + + /** + * string producerGroup = 3; + */ + public com.google.protobuf.ByteString + getProducerGroupBytes() { + return ByteString.copyFromUtf8(producerGroup_); + } + + /** + * string producerGroup = 3; + */ + public Builder setProducerGroup( + String value) { + Objects.requireNonNull(value, "ProducerGroup can not be null"); + + producerGroup_ = value; + onChanged(); + return this; + } + + /** + * string producerGroup = 3; + */ + public Builder clearProducerGroup() { + + producerGroup_ = getDefaultInstance().getProducerGroup(); + onChanged(); + return this; + } + + /** + * string producerGroup = 3; + */ + public Builder setProducerGroupBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "ProducerGroupBytes can not be null"); + checkByteStringIsUtf8(value); + + producerGroup_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String consumerGroup_ = ""; + + /** + * string consumerGroup = 4; + */ + public String getConsumerGroup() { + return consumerGroup_; + } + + /** + * string consumerGroup = 4; + */ + public com.google.protobuf.ByteString + getConsumerGroupBytes() { + return ByteString.copyFromUtf8(consumerGroup_); + } + + /** + * string consumerGroup = 4; + */ + public Builder setConsumerGroup( + String value) { + Objects.requireNonNull(value, "ConsumerGroup can not be null"); + + consumerGroup_ = value; + onChanged(); + return this; + } + + /** + * string consumerGroup = 4; + */ + public Builder clearConsumerGroup() { + + consumerGroup_ = getDefaultInstance().getConsumerGroup(); + onChanged(); + return this; + } + + /** + * string consumerGroup = 4; + */ + public Builder setConsumerGroupBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "ConsumerGroupBytes can not be null"); + checkByteStringIsUtf8(value); + + consumerGroup_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private java.util.List heartbeatItems_ = + java.util.Collections.emptyList(); + + private void ensureHeartbeatItemsIsMutable() { + if (!((bitField0_ & 0x00000010) == 0x00000010)) { + heartbeatItems_ = new java.util.ArrayList(heartbeatItems_); + bitField0_ |= 0x00000010; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + HeartbeatItem, HeartbeatItem.Builder, HeartbeatItemOrBuilder> heartbeatItemsBuilder_; + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public java.util.List getHeartbeatItemsList() { + if (heartbeatItemsBuilder_ == null) { + return java.util.Collections.unmodifiableList(heartbeatItems_); + } else { + return heartbeatItemsBuilder_.getMessageList(); + } + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public int getHeartbeatItemsCount() { + if (heartbeatItemsBuilder_ == null) { + return heartbeatItems_.size(); + } else { + return heartbeatItemsBuilder_.getCount(); + } + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public HeartbeatItem getHeartbeatItems(int index) { + if (heartbeatItemsBuilder_ == null) { + return heartbeatItems_.get(index); + } else { + return heartbeatItemsBuilder_.getMessage(index); + } + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public Builder setHeartbeatItems( + int index, HeartbeatItem value) { + if (heartbeatItemsBuilder_ == null) { + Objects.requireNonNull(value, "HeartbeatItem can not be null"); + ensureHeartbeatItemsIsMutable(); + heartbeatItems_.set(index, value); + onChanged(); + } else { + heartbeatItemsBuilder_.setMessage(index, value); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public Builder setHeartbeatItems( + int index, HeartbeatItem.Builder builderForValue) { + if (heartbeatItemsBuilder_ == null) { + ensureHeartbeatItemsIsMutable(); + heartbeatItems_.set(index, builderForValue.build()); + onChanged(); + } else { + heartbeatItemsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public Builder addHeartbeatItems(HeartbeatItem value) { + if (heartbeatItemsBuilder_ == null) { + Objects.requireNonNull(value, "HeartbeatItem can not be null"); + ensureHeartbeatItemsIsMutable(); + heartbeatItems_.add(value); + onChanged(); + } else { + heartbeatItemsBuilder_.addMessage(value); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public Builder addHeartbeatItems( + int index, HeartbeatItem value) { + if (heartbeatItemsBuilder_ == null) { + Objects.requireNonNull(value, "HeartbeatItem can not be null"); + ensureHeartbeatItemsIsMutable(); + heartbeatItems_.add(index, value); + onChanged(); + } else { + heartbeatItemsBuilder_.addMessage(index, value); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public Builder addHeartbeatItems( + HeartbeatItem.Builder builderForValue) { + if (heartbeatItemsBuilder_ == null) { + ensureHeartbeatItemsIsMutable(); + heartbeatItems_.add(builderForValue.build()); + onChanged(); + } else { + heartbeatItemsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public Builder addHeartbeatItems( + int index, HeartbeatItem.Builder builderForValue) { + if (heartbeatItemsBuilder_ == null) { + ensureHeartbeatItemsIsMutable(); + heartbeatItems_.add(index, builderForValue.build()); + onChanged(); + } else { + heartbeatItemsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public Builder addAllHeartbeatItems( + Iterable values) { + if (heartbeatItemsBuilder_ == null) { + ensureHeartbeatItemsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, heartbeatItems_); + onChanged(); + } else { + heartbeatItemsBuilder_.addAllMessages(values); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public Builder clearHeartbeatItems() { + if (heartbeatItemsBuilder_ == null) { + heartbeatItems_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000010); + onChanged(); + } else { + heartbeatItemsBuilder_.clear(); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public Builder removeHeartbeatItems(int index) { + if (heartbeatItemsBuilder_ == null) { + ensureHeartbeatItemsIsMutable(); + heartbeatItems_.remove(index); + onChanged(); + } else { + heartbeatItemsBuilder_.remove(index); + } + return this; + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public HeartbeatItem.Builder getHeartbeatItemsBuilder( + int index) { + return getHeartbeatItemsFieldBuilder().getBuilder(index); + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public HeartbeatItemOrBuilder getHeartbeatItemsOrBuilder( + int index) { + if (heartbeatItemsBuilder_ == null) { + return heartbeatItems_.get(index); + } else { + return heartbeatItemsBuilder_.getMessageOrBuilder(index); + } + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public java.util.List + getHeartbeatItemsOrBuilderList() { + if (heartbeatItemsBuilder_ != null) { + return heartbeatItemsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(heartbeatItems_); + } + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public HeartbeatItem.Builder addHeartbeatItemsBuilder() { + return getHeartbeatItemsFieldBuilder().addBuilder( + HeartbeatItem.getDefaultInstance()); + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public HeartbeatItem.Builder addHeartbeatItemsBuilder( + int index) { + return getHeartbeatItemsFieldBuilder().addBuilder( + index, HeartbeatItem.getDefaultInstance()); + } + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + public java.util.List + getHeartbeatItemsBuilderList() { + return getHeartbeatItemsFieldBuilder().getBuilderList(); + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + HeartbeatItem, HeartbeatItem.Builder, HeartbeatItemOrBuilder> + getHeartbeatItemsFieldBuilder() { + if (heartbeatItemsBuilder_ == null) { + heartbeatItemsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + HeartbeatItem, HeartbeatItem.Builder, HeartbeatItemOrBuilder>( + heartbeatItems_, + ((bitField0_ & 0x00000010) == 0x00000010), + getParentForChildren(), + isClean()); + heartbeatItems_ = null; + } + return heartbeatItemsBuilder_; + } + + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFieldsProto3(unknownFields); + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.common.protocol.grpc.Heartbeat) + } + + // @@protoc_insertion_point(class_scope:eventmesh.common.protocol.grpc.Heartbeat) + private static final Heartbeat DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new Heartbeat(); + } + + public static Heartbeat getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public Heartbeat parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Heartbeat(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public Heartbeat getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/HeartbeatOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/HeartbeatOrBuilder.java new file mode 100644 index 0000000000..c3cddbdb4b --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/HeartbeatOrBuilder.java @@ -0,0 +1,93 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +@SuppressWarnings({"all"}) +public interface HeartbeatOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.common.protocol.grpc.Heartbeat) + com.google.protobuf.MessageOrBuilder { + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + boolean hasHeader(); + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + RequestHeader getHeader(); + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + RequestHeaderOrBuilder getHeaderOrBuilder(); + + /** + * .eventmesh.common.protocol.grpc.Heartbeat.ClientType clientType = 2; + */ + int getClientTypeValue(); + /** + * .eventmesh.common.protocol.grpc.Heartbeat.ClientType clientType = 2; + */ + Heartbeat.ClientType getClientType(); + + /** + * string producerGroup = 3; + */ + String getProducerGroup(); + /** + * string producerGroup = 3; + */ + com.google.protobuf.ByteString + getProducerGroupBytes(); + + /** + * string consumerGroup = 4; + */ + String getConsumerGroup(); + /** + * string consumerGroup = 4; + */ + com.google.protobuf.ByteString + getConsumerGroupBytes(); + + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + java.util.List + getHeartbeatItemsList(); + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + Heartbeat.HeartbeatItem getHeartbeatItems(int index); + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + int getHeartbeatItemsCount(); + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + java.util.List + getHeartbeatItemsOrBuilderList(); + /** + * repeated .eventmesh.common.protocol.grpc.Heartbeat.HeartbeatItem heartbeatItems = 5; + */ + Heartbeat.HeartbeatItemOrBuilder getHeartbeatItemsOrBuilder( + int index); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/HeartbeatServiceGrpc.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/HeartbeatServiceGrpc.java new file mode 100644 index 0000000000..dca914b039 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/HeartbeatServiceGrpc.java @@ -0,0 +1,290 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.grpc.protos; + +import static io.grpc.MethodDescriptor.generateFullMethodName; +import static io.grpc.stub.ClientCalls.asyncUnaryCall; +import static io.grpc.stub.ClientCalls.blockingUnaryCall; +import static io.grpc.stub.ClientCalls.futureUnaryCall; +import static io.grpc.stub.ServerCalls.asyncUnaryCall; +import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; + +/** + */ +@SuppressWarnings({"all"}) +@javax.annotation.Generated( + value = "by gRPC proto compiler (version 1.42.2)", + comments = "Source: eventmesh-client.proto") +public final class HeartbeatServiceGrpc { + + private HeartbeatServiceGrpc() {} + + public static final String SERVICE_NAME = "eventmesh.common.protocol.grpc.HeartbeatService"; + + // Static method descriptors that strictly reflect the proto. + private static volatile io.grpc.MethodDescriptor getHeartbeatMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "heartbeat", + requestType = Heartbeat.class, + responseType = Response.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getHeartbeatMethod() { + io.grpc.MethodDescriptor getHeartbeatMethod; + if ((getHeartbeatMethod = HeartbeatServiceGrpc.getHeartbeatMethod) == null) { + synchronized (HeartbeatServiceGrpc.class) { + if ((getHeartbeatMethod = HeartbeatServiceGrpc.getHeartbeatMethod) == null) { + HeartbeatServiceGrpc.getHeartbeatMethod = getHeartbeatMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName( + "eventmesh.common.protocol.grpc.HeartbeatService", "heartbeat")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + Heartbeat.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + Response.getDefaultInstance())) + .setSchemaDescriptor(new HeartbeatServiceMethodDescriptorSupplier("heartbeat")) + .build(); + } + } + } + return getHeartbeatMethod; + } + + /** + * Creates a new async stub that supports all call types for the service + */ + public static HeartbeatServiceStub newStub(io.grpc.Channel channel) { + return new HeartbeatServiceStub(channel); + } + + /** + * Creates a new blocking-style stub that supports unary and streaming output calls on the service + */ + public static HeartbeatServiceBlockingStub newBlockingStub( + io.grpc.Channel channel) { + return new HeartbeatServiceBlockingStub(channel); + } + + /** + * Creates a new ListenableFuture-style stub that supports unary calls on the service + */ + public static HeartbeatServiceFutureStub newFutureStub( + io.grpc.Channel channel) { + return new HeartbeatServiceFutureStub(channel); + } + + /** + */ + public static abstract class HeartbeatServiceImplBase implements io.grpc.BindableService { + + /** + */ + public void heartbeat(Heartbeat request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnimplementedUnaryCall(getHeartbeatMethod(), responseObserver); + } + + @Override public final io.grpc.ServerServiceDefinition bindService() { + return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) + .addMethod( + getHeartbeatMethod(), + asyncUnaryCall( + new MethodHandlers< + Heartbeat, + Response>( + this, METHODID_HEARTBEAT))) + .build(); + } + } + + /** + */ + public static final class HeartbeatServiceStub extends io.grpc.stub.AbstractStub { + private HeartbeatServiceStub(io.grpc.Channel channel) { + super(channel); + } + + private HeartbeatServiceStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected HeartbeatServiceStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new HeartbeatServiceStub(channel, callOptions); + } + + /** + */ + public void heartbeat(Heartbeat request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + getChannel().newCall(getHeartbeatMethod(), getCallOptions()), request, responseObserver); + } + } + + /** + */ + public static final class HeartbeatServiceBlockingStub extends io.grpc.stub.AbstractStub { + private HeartbeatServiceBlockingStub(io.grpc.Channel channel) { + super(channel); + } + + private HeartbeatServiceBlockingStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected HeartbeatServiceBlockingStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new HeartbeatServiceBlockingStub(channel, callOptions); + } + + /** + */ + public Response heartbeat(Heartbeat request) { + return blockingUnaryCall( + getChannel(), getHeartbeatMethod(), getCallOptions(), request); + } + } + + /** + */ + public static final class HeartbeatServiceFutureStub extends io.grpc.stub.AbstractStub { + private HeartbeatServiceFutureStub(io.grpc.Channel channel) { + super(channel); + } + + private HeartbeatServiceFutureStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected HeartbeatServiceFutureStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new HeartbeatServiceFutureStub(channel, callOptions); + } + + /** + */ + public com.google.common.util.concurrent.ListenableFuture heartbeat( + Heartbeat request) { + return futureUnaryCall( + getChannel().newCall(getHeartbeatMethod(), getCallOptions()), request); + } + } + + private static final int METHODID_HEARTBEAT = 0; + + private static final class MethodHandlers implements + io.grpc.stub.ServerCalls.UnaryMethod, + io.grpc.stub.ServerCalls.ServerStreamingMethod, + io.grpc.stub.ServerCalls.ClientStreamingMethod, + io.grpc.stub.ServerCalls.BidiStreamingMethod { + private final HeartbeatServiceImplBase serviceImpl; + private final int methodId; + + MethodHandlers(HeartbeatServiceImplBase serviceImpl, int methodId) { + this.serviceImpl = serviceImpl; + this.methodId = methodId; + } + + @Override + @SuppressWarnings("unchecked") + public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + case METHODID_HEARTBEAT: + serviceImpl.heartbeat((Heartbeat) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + default: + throw new AssertionError(); + } + } + + @Override + @SuppressWarnings("unchecked") + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + default: + throw new AssertionError(); + } + } + } + + private static abstract class HeartbeatServiceBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier { + HeartbeatServiceBaseDescriptorSupplier() {} + + @Override + public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { + return EventmeshGrpc.getDescriptor(); + } + + @Override + public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() { + return getFileDescriptor().findServiceByName("HeartbeatService"); + } + } + + private static final class HeartbeatServiceFileDescriptorSupplier + extends HeartbeatServiceBaseDescriptorSupplier { + HeartbeatServiceFileDescriptorSupplier() {} + } + + private static final class HeartbeatServiceMethodDescriptorSupplier + extends HeartbeatServiceBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoMethodDescriptorSupplier { + private final String methodName; + + HeartbeatServiceMethodDescriptorSupplier(String methodName) { + this.methodName = methodName; + } + + @Override + public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() { + return getServiceDescriptor().findMethodByName(methodName); + } + } + + private static volatile io.grpc.ServiceDescriptor serviceDescriptor; + + public static io.grpc.ServiceDescriptor getServiceDescriptor() { + io.grpc.ServiceDescriptor result = serviceDescriptor; + if (result == null) { + synchronized (HeartbeatServiceGrpc.class) { + result = serviceDescriptor; + if (result == null) { + serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) + .setSchemaDescriptor(new HeartbeatServiceFileDescriptorSupplier()) + .addMethod(getHeartbeatMethod()) + .build(); + } + } + } + return result; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/PublisherServiceGrpc.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/PublisherServiceGrpc.java new file mode 100644 index 0000000000..20f3a23c17 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/PublisherServiceGrpc.java @@ -0,0 +1,476 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.grpc.protos; + +import static io.grpc.MethodDescriptor.generateFullMethodName; +import static io.grpc.stub.ClientCalls.asyncUnaryCall; +import static io.grpc.stub.ClientCalls.blockingUnaryCall; +import static io.grpc.stub.ClientCalls.futureUnaryCall; +import static io.grpc.stub.ServerCalls.asyncUnaryCall; +import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; + +/** + */ +@SuppressWarnings({"all"}) +@javax.annotation.Generated( + value = "by gRPC proto compiler (version 1.42.2)", + comments = "Source: eventmesh-client.proto") +public final class PublisherServiceGrpc { + + private PublisherServiceGrpc() {} + + public static final String SERVICE_NAME = "eventmesh.common.protocol.grpc.PublisherService"; + + // Static method descriptors that strictly reflect the proto. + private static volatile io.grpc.MethodDescriptor getPublishMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "publish", + requestType = SimpleMessage.class, + responseType = Response.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getPublishMethod() { + io.grpc.MethodDescriptor getPublishMethod; + if ((getPublishMethod = PublisherServiceGrpc.getPublishMethod) == null) { + synchronized (PublisherServiceGrpc.class) { + if ((getPublishMethod = PublisherServiceGrpc.getPublishMethod) == null) { + PublisherServiceGrpc.getPublishMethod = getPublishMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName( + "eventmesh.common.protocol.grpc.PublisherService", "publish")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + SimpleMessage.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + Response.getDefaultInstance())) + .setSchemaDescriptor(new PublisherServiceMethodDescriptorSupplier("publish")) + .build(); + } + } + } + return getPublishMethod; + } + + private static volatile io.grpc.MethodDescriptor getRequestReplyMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "requestReply", + requestType = SimpleMessage.class, + responseType = SimpleMessage.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getRequestReplyMethod() { + io.grpc.MethodDescriptor getRequestReplyMethod; + if ((getRequestReplyMethod = PublisherServiceGrpc.getRequestReplyMethod) == null) { + synchronized (PublisherServiceGrpc.class) { + if ((getRequestReplyMethod = PublisherServiceGrpc.getRequestReplyMethod) == null) { + PublisherServiceGrpc.getRequestReplyMethod = getRequestReplyMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName( + "eventmesh.common.protocol.grpc.PublisherService", "requestReply")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + SimpleMessage.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + SimpleMessage.getDefaultInstance())) + .setSchemaDescriptor(new PublisherServiceMethodDescriptorSupplier("requestReply")) + .build(); + } + } + } + return getRequestReplyMethod; + } + + private static volatile io.grpc.MethodDescriptor getBatchPublishMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "batchPublish", + requestType = BatchMessage.class, + responseType = Response.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getBatchPublishMethod() { + io.grpc.MethodDescriptor getBatchPublishMethod; + if ((getBatchPublishMethod = PublisherServiceGrpc.getBatchPublishMethod) == null) { + synchronized (PublisherServiceGrpc.class) { + if ((getBatchPublishMethod = PublisherServiceGrpc.getBatchPublishMethod) == null) { + PublisherServiceGrpc.getBatchPublishMethod = getBatchPublishMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName( + "eventmesh.common.protocol.grpc.PublisherService", "batchPublish")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + BatchMessage.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + Response.getDefaultInstance())) + .setSchemaDescriptor(new PublisherServiceMethodDescriptorSupplier("batchPublish")) + .build(); + } + } + } + return getBatchPublishMethod; + } + + /** + * Creates a new async stub that supports all call types for the service + */ + public static PublisherServiceStub newStub(io.grpc.Channel channel) { + return new PublisherServiceStub(channel); + } + + /** + * Creates a new blocking-style stub that supports unary and streaming output calls on the service + */ + public static PublisherServiceBlockingStub newBlockingStub( + io.grpc.Channel channel) { + return new PublisherServiceBlockingStub(channel); + } + + /** + * Creates a new ListenableFuture-style stub that supports unary calls on the service + */ + public static PublisherServiceFutureStub newFutureStub( + io.grpc.Channel channel) { + return new PublisherServiceFutureStub(channel); + } + + /** + */ + public static abstract class PublisherServiceImplBase implements io.grpc.BindableService { + + /** + *
+     * Async event publish
+     * 
+ */ + public void publish(SimpleMessage request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnimplementedUnaryCall(getPublishMethod(), responseObserver); + } + + /** + *
+     * Sync event publish
+     * 
+ */ + public void requestReply(SimpleMessage request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnimplementedUnaryCall(getRequestReplyMethod(), responseObserver); + } + + /** + *
+     * Async batch event publish
+     * 
+ */ + public void batchPublish(BatchMessage request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnimplementedUnaryCall(getBatchPublishMethod(), responseObserver); + } + + @Override public final io.grpc.ServerServiceDefinition bindService() { + return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) + .addMethod( + getPublishMethod(), + asyncUnaryCall( + new MethodHandlers< + SimpleMessage, + Response>( + this, METHODID_PUBLISH))) + .addMethod( + getRequestReplyMethod(), + asyncUnaryCall( + new MethodHandlers< + SimpleMessage, + SimpleMessage>( + this, METHODID_REQUEST_REPLY))) + .addMethod( + getBatchPublishMethod(), + asyncUnaryCall( + new MethodHandlers< + BatchMessage, + Response>( + this, METHODID_BATCH_PUBLISH))) + .build(); + } + } + + /** + */ + public static final class PublisherServiceStub extends io.grpc.stub.AbstractStub { + private PublisherServiceStub(io.grpc.Channel channel) { + super(channel); + } + + private PublisherServiceStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected PublisherServiceStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new PublisherServiceStub(channel, callOptions); + } + + /** + *
+     * Async event publish
+     * 
+ */ + public void publish(SimpleMessage request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + getChannel().newCall(getPublishMethod(), getCallOptions()), request, responseObserver); + } + + /** + *
+     * Sync event publish
+     * 
+ */ + public void requestReply(SimpleMessage request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + getChannel().newCall(getRequestReplyMethod(), getCallOptions()), request, responseObserver); + } + + /** + *
+     * Async batch event publish
+     * 
+ */ + public void batchPublish(BatchMessage request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + getChannel().newCall(getBatchPublishMethod(), getCallOptions()), request, responseObserver); + } + } + + /** + */ + public static final class PublisherServiceBlockingStub extends io.grpc.stub.AbstractStub { + private PublisherServiceBlockingStub(io.grpc.Channel channel) { + super(channel); + } + + private PublisherServiceBlockingStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected PublisherServiceBlockingStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new PublisherServiceBlockingStub(channel, callOptions); + } + + /** + *
+     * Async event publish
+     * 
+ */ + public Response publish(SimpleMessage request) { + return blockingUnaryCall( + getChannel(), getPublishMethod(), getCallOptions(), request); + } + + /** + *
+     * Sync event publish
+     * 
+ */ + public SimpleMessage requestReply(SimpleMessage request) { + return blockingUnaryCall( + getChannel(), getRequestReplyMethod(), getCallOptions(), request); + } + + /** + *
+     * Async batch event publish
+     * 
+ */ + public Response batchPublish(BatchMessage request) { + return blockingUnaryCall( + getChannel(), getBatchPublishMethod(), getCallOptions(), request); + } + } + + /** + */ + public static final class PublisherServiceFutureStub extends io.grpc.stub.AbstractStub { + private PublisherServiceFutureStub(io.grpc.Channel channel) { + super(channel); + } + + private PublisherServiceFutureStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected PublisherServiceFutureStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new PublisherServiceFutureStub(channel, callOptions); + } + + /** + *
+     * Async event publish
+     * 
+ */ + public com.google.common.util.concurrent.ListenableFuture publish( + SimpleMessage request) { + return futureUnaryCall( + getChannel().newCall(getPublishMethod(), getCallOptions()), request); + } + + /** + *
+     * Sync event publish
+     * 
+ */ + public com.google.common.util.concurrent.ListenableFuture requestReply( + SimpleMessage request) { + return futureUnaryCall( + getChannel().newCall(getRequestReplyMethod(), getCallOptions()), request); + } + + /** + *
+     * Async batch event publish
+     * 
+ */ + public com.google.common.util.concurrent.ListenableFuture batchPublish( + BatchMessage request) { + return futureUnaryCall( + getChannel().newCall(getBatchPublishMethod(), getCallOptions()), request); + } + } + + private static final int METHODID_PUBLISH = 0; + private static final int METHODID_REQUEST_REPLY = 1; + private static final int METHODID_BATCH_PUBLISH = 2; + + private static final class MethodHandlers implements + io.grpc.stub.ServerCalls.UnaryMethod, + io.grpc.stub.ServerCalls.ServerStreamingMethod, + io.grpc.stub.ServerCalls.ClientStreamingMethod, + io.grpc.stub.ServerCalls.BidiStreamingMethod { + private final PublisherServiceImplBase serviceImpl; + private final int methodId; + + MethodHandlers(PublisherServiceImplBase serviceImpl, int methodId) { + this.serviceImpl = serviceImpl; + this.methodId = methodId; + } + + @Override + @SuppressWarnings("unchecked") + public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + case METHODID_PUBLISH: + serviceImpl.publish((SimpleMessage) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_REQUEST_REPLY: + serviceImpl.requestReply((SimpleMessage) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_BATCH_PUBLISH: + serviceImpl.batchPublish((BatchMessage) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + default: + throw new AssertionError(); + } + } + + @Override + @SuppressWarnings("unchecked") + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + default: + throw new AssertionError(); + } + } + } + + private static abstract class PublisherServiceBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier { + PublisherServiceBaseDescriptorSupplier() {} + + @Override + public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { + return EventmeshGrpc.getDescriptor(); + } + + @Override + public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() { + return getFileDescriptor().findServiceByName("PublisherService"); + } + } + + private static final class PublisherServiceFileDescriptorSupplier + extends PublisherServiceBaseDescriptorSupplier { + PublisherServiceFileDescriptorSupplier() {} + } + + private static final class PublisherServiceMethodDescriptorSupplier + extends PublisherServiceBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoMethodDescriptorSupplier { + private final String methodName; + + PublisherServiceMethodDescriptorSupplier(String methodName) { + this.methodName = methodName; + } + + @Override + public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() { + return getServiceDescriptor().findMethodByName(methodName); + } + } + + private static volatile io.grpc.ServiceDescriptor serviceDescriptor; + + public static io.grpc.ServiceDescriptor getServiceDescriptor() { + io.grpc.ServiceDescriptor result = serviceDescriptor; + if (result == null) { + synchronized (PublisherServiceGrpc.class) { + result = serviceDescriptor; + if (result == null) { + serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) + .setSchemaDescriptor(new PublisherServiceFileDescriptorSupplier()) + .addMethod(getPublishMethod()) + .addMethod(getRequestReplyMethod()) + .addMethod(getBatchPublishMethod()) + .build(); + } + } + } + return result; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/RequestHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/RequestHeader.java new file mode 100644 index 0000000000..21b23be268 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/RequestHeader.java @@ -0,0 +1,1507 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +import java.util.Objects; + +import com.google.protobuf.ByteString; + +/** + * Protobuf type {@code eventmesh.common.protocol.grpc.RequestHeader} + */ +@SuppressWarnings({"all"}) +public final class RequestHeader extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.common.protocol.grpc.RequestHeader) + RequestHeaderOrBuilder { + + private static final long serialVersionUID = 51630109646794056L; + + // Use RequestHeader.newBuilder() to construct. + private RequestHeader(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private RequestHeader() { + env_ = ""; + region_ = ""; + idc_ = ""; + ip_ = ""; + pid_ = ""; + sys_ = ""; + username_ = ""; + password_ = ""; + language_ = ""; + protocolType_ = ""; + protocolVersion_ = ""; + protocolDesc_ = ""; + } + + @Override + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { + return this.unknownFields; + } + + private RequestHeader( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + Objects.requireNonNull(input, "CodedInputStream can not be null"); + Objects.requireNonNull(extensionRegistry, "ExtensionRegistryLite can not be null"); + + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownFieldProto3( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + env_ = input.readStringRequireUtf8(); + break; + } + case 18: { + region_ = input.readStringRequireUtf8(); + break; + } + case 26: { + idc_ = input.readStringRequireUtf8(); + break; + } + case 34: { + ip_ = input.readStringRequireUtf8(); + break; + } + case 42: { + pid_ = input.readStringRequireUtf8(); + break; + } + case 50: { + sys_ = input.readStringRequireUtf8(); + break; + } + case 58: { + username_ = input.readStringRequireUtf8(); + break; + } + case 66: { + password_ = input.readStringRequireUtf8(); + break; + } + case 74: { + language_ = input.readStringRequireUtf8(); + break; + } + case 82: { + protocolType_ = input.readStringRequireUtf8(); + break; + } + case 90: { + protocolVersion_ = input.readStringRequireUtf8(); + break; + } + case 98: { + protocolDesc_ = input.readStringRequireUtf8(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_RequestHeader_descriptor; + } + + protected FieldAccessorTable internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_RequestHeader_fieldAccessorTable + .ensureFieldAccessorsInitialized( + RequestHeader.class, Builder.class); + } + + public static final int ENV_FIELD_NUMBER = 1; + private volatile String env_; + + /** + * string env = 1; + */ + public String getEnv() { + return env_; + } + + /** + * string env = 1; + */ + public com.google.protobuf.ByteString getEnvBytes() { + return ByteString.copyFromUtf8(env_); + } + + public static final int REGION_FIELD_NUMBER = 2; + private volatile String region_; + + /** + * string region = 2; + */ + public String getRegion() { + return region_; + } + + /** + * string region = 2; + */ + public com.google.protobuf.ByteString getRegionBytes() { + return ByteString.copyFromUtf8(region_); + } + + public static final int IDC_FIELD_NUMBER = 3; + private volatile String idc_; + + /** + * string idc = 3; + */ + public String getIdc() { + return idc_; + } + + /** + * string idc = 3; + */ + public com.google.protobuf.ByteString getIdcBytes() { + return ByteString.copyFromUtf8(idc_); + } + + public static final int IP_FIELD_NUMBER = 4; + private volatile String ip_; + + /** + * string ip = 4; + */ + public String getIp() { + return ip_; + } + + /** + * string ip = 4; + */ + public com.google.protobuf.ByteString getIpBytes() { + return ByteString.copyFromUtf8(ip_); + } + + public static final int PID_FIELD_NUMBER = 5; + private volatile String pid_; + + /** + * string pid = 5; + */ + public String getPid() { + return pid_; + } + + /** + * string pid = 5; + */ + public com.google.protobuf.ByteString getPidBytes() { + return ByteString.copyFromUtf8(pid_); + } + + public static final int SYS_FIELD_NUMBER = 6; + private volatile String sys_; + + /** + * string sys = 6; + */ + public String getSys() { + return sys_; + } + + /** + * string sys = 6; + */ + public com.google.protobuf.ByteString getSysBytes() { + return ByteString.copyFromUtf8(sys_); + } + + public static final int USERNAME_FIELD_NUMBER = 7; + private volatile String username_; + + /** + * string username = 7; + */ + public String getUsername() { + return username_; + } + + /** + * string username = 7; + */ + public com.google.protobuf.ByteString getUsernameBytes() { + return ByteString.copyFromUtf8(username_); + } + + public static final int PASSWORD_FIELD_NUMBER = 8; + private volatile String password_; + + /** + * string password = 8; + */ + public String getPassword() { + return password_; + } + + /** + * string password = 8; + */ + public com.google.protobuf.ByteString + getPasswordBytes() { + return ByteString.copyFromUtf8(password_); + } + + public static final int LANGUAGE_FIELD_NUMBER = 9; + private volatile String language_; + + /** + * string language = 9; + */ + public String getLanguage() { + return language_; + } + + /** + * string language = 9; + */ + public com.google.protobuf.ByteString getLanguageBytes() { + return ByteString.copyFromUtf8(language_); + } + + public static final int PROTOCOLTYPE_FIELD_NUMBER = 10; + private volatile String protocolType_; + + /** + * string protocolType = 10; + */ + public String getProtocolType() { + return protocolType_; + } + + /** + * string protocolType = 10; + */ + public com.google.protobuf.ByteString + getProtocolTypeBytes() { + return ByteString.copyFromUtf8(protocolType_); + } + + public static final int PROTOCOLVERSION_FIELD_NUMBER = 11; + private volatile String protocolVersion_; + + /** + * string protocolVersion = 11; + */ + public String getProtocolVersion() { + return protocolVersion_; + } + + /** + * string protocolVersion = 11; + */ + public com.google.protobuf.ByteString getProtocolVersionBytes() { + return ByteString.copyFromUtf8(protocolVersion_); + } + + public static final int PROTOCOLDESC_FIELD_NUMBER = 12; + private volatile String protocolDesc_; + + /** + * string protocolDesc = 12; + */ + public String getProtocolDesc() { + return protocolDesc_; + } + + /** + * string protocolDesc = 12; + */ + public com.google.protobuf.ByteString getProtocolDescBytes() { + return ByteString.copyFromUtf8(protocolDesc_); + } + + private byte memoizedIsInitialized = -1; + + public final boolean isInitialized() { + if (memoizedIsInitialized == 1) return true; + if (memoizedIsInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getEnvBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, env_); + } + if (!getRegionBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, region_); + } + if (!getIdcBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, idc_); + } + if (!getIpBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 4, ip_); + } + if (!getPidBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 5, pid_); + } + if (!getSysBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 6, sys_); + } + if (!getUsernameBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 7, username_); + } + if (!getPasswordBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 8, password_); + } + if (!getLanguageBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 9, language_); + } + if (!getProtocolTypeBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 10, protocolType_); + } + if (!getProtocolVersionBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 11, protocolVersion_); + } + if (!getProtocolDescBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 12, protocolDesc_); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getEnvBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, env_); + } + if (!getRegionBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, region_); + } + if (!getIdcBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, idc_); + } + if (!getIpBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, ip_); + } + if (!getPidBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(5, pid_); + } + if (!getSysBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(6, sys_); + } + if (!getUsernameBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(7, username_); + } + if (!getPasswordBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(8, password_); + } + if (!getLanguageBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(9, language_); + } + if (!getProtocolTypeBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(10, protocolType_); + } + if (!getProtocolVersionBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(11, protocolVersion_); + } + if (!getProtocolDescBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(12, protocolDesc_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof RequestHeader)) { + return super.equals(obj); + } + RequestHeader other = (RequestHeader) obj; + + return getEnv().equals(other.getEnv()) + && getRegion().equals(other.getRegion()) + && getIdc().equals(other.getIdc()) + && getIp().equals(other.getIp()) + && getPid().equals(other.getPid()) + && getSys().equals(other.getSys()) + && getUsername().equals(other.getUsername()) + && getPassword().equals(other.getPassword()) + && getLanguage().equals(other.getLanguage()) + && getProtocolType().equals(other.getProtocolType()) + && getProtocolVersion().equals(other.getProtocolVersion()) + && getProtocolDesc().equals(other.getProtocolDesc()) + && unknownFields.equals(other.unknownFields); + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + ENV_FIELD_NUMBER; + hash = (53 * hash) + getEnv().hashCode(); + hash = (37 * hash) + REGION_FIELD_NUMBER; + hash = (53 * hash) + getRegion().hashCode(); + hash = (37 * hash) + IDC_FIELD_NUMBER; + hash = (53 * hash) + getIdc().hashCode(); + hash = (37 * hash) + IP_FIELD_NUMBER; + hash = (53 * hash) + getIp().hashCode(); + hash = (37 * hash) + PID_FIELD_NUMBER; + hash = (53 * hash) + getPid().hashCode(); + hash = (37 * hash) + SYS_FIELD_NUMBER; + hash = (53 * hash) + getSys().hashCode(); + hash = (37 * hash) + USERNAME_FIELD_NUMBER; + hash = (53 * hash) + getUsername().hashCode(); + hash = (37 * hash) + PASSWORD_FIELD_NUMBER; + hash = (53 * hash) + getPassword().hashCode(); + hash = (37 * hash) + LANGUAGE_FIELD_NUMBER; + hash = (53 * hash) + getLanguage().hashCode(); + hash = (37 * hash) + PROTOCOLTYPE_FIELD_NUMBER; + hash = (53 * hash) + getProtocolType().hashCode(); + hash = (37 * hash) + PROTOCOLVERSION_FIELD_NUMBER; + hash = (53 * hash) + getProtocolVersion().hashCode(); + hash = (37 * hash) + PROTOCOLDESC_FIELD_NUMBER; + hash = (53 * hash) + getProtocolDesc().hashCode(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static RequestHeader parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static RequestHeader parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static RequestHeader parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static RequestHeader parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static RequestHeader parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static RequestHeader parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static RequestHeader parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static RequestHeader parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static RequestHeader parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static RequestHeader parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static RequestHeader parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static RequestHeader parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(RequestHeader prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType(BuilderParent parent) { + return new Builder(parent); + } + + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.RequestHeader} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.common.protocol.grpc.RequestHeader) + RequestHeaderOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_RequestHeader_descriptor; + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_RequestHeader_fieldAccessorTable + .ensureFieldAccessorsInitialized( + RequestHeader.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.grpc.protos.RequestHeader.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + + public Builder clear() { + super.clear(); + env_ = ""; + + region_ = ""; + + idc_ = ""; + + ip_ = ""; + + pid_ = ""; + + sys_ = ""; + + username_ = ""; + + password_ = ""; + + language_ = ""; + + protocolType_ = ""; + + protocolVersion_ = ""; + + protocolDesc_ = ""; + + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_RequestHeader_descriptor; + } + + public RequestHeader getDefaultInstanceForType() { + return RequestHeader.getDefaultInstance(); + } + + public RequestHeader build() { + RequestHeader result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public RequestHeader buildPartial() { + RequestHeader result = new RequestHeader(this); + result.env_ = env_; + result.region_ = region_; + result.idc_ = idc_; + result.ip_ = ip_; + result.pid_ = pid_; + result.sys_ = sys_; + result.username_ = username_; + result.password_ = password_; + result.language_ = language_; + result.protocolType_ = protocolType_; + result.protocolVersion_ = protocolVersion_; + result.protocolDesc_ = protocolDesc_; + onBuilt(); + return result; + } + + public Builder clone() { + return (Builder) super.clone(); + } + + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.setField(field, value); + } + + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return (Builder) super.clearField(field); + } + + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return (Builder) super.clearOneof(oneof); + } + + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return (Builder) super.setRepeatedField(field, index, value); + } + + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.addRepeatedField(field, value); + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof RequestHeader) { + return mergeFrom((RequestHeader) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(RequestHeader other) { + if (other == RequestHeader.getDefaultInstance()) return this; + if (!other.getEnv().isEmpty()) { + env_ = other.env_; + onChanged(); + } + if (!other.getRegion().isEmpty()) { + region_ = other.region_; + onChanged(); + } + if (!other.getIdc().isEmpty()) { + idc_ = other.idc_; + onChanged(); + } + if (!other.getIp().isEmpty()) { + ip_ = other.ip_; + onChanged(); + } + if (!other.getPid().isEmpty()) { + pid_ = other.pid_; + onChanged(); + } + if (!other.getSys().isEmpty()) { + sys_ = other.sys_; + onChanged(); + } + if (!other.getUsername().isEmpty()) { + username_ = other.username_; + onChanged(); + } + if (!other.getPassword().isEmpty()) { + password_ = other.password_; + onChanged(); + } + if (!other.getLanguage().isEmpty()) { + language_ = other.language_; + onChanged(); + } + if (!other.getProtocolType().isEmpty()) { + protocolType_ = other.protocolType_; + onChanged(); + } + if (!other.getProtocolVersion().isEmpty()) { + protocolVersion_ = other.protocolVersion_; + onChanged(); + } + if (!other.getProtocolDesc().isEmpty()) { + protocolDesc_ = other.protocolDesc_; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + RequestHeader parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (RequestHeader) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private String env_ = ""; + + /** + * string env = 1; + */ + public String getEnv() { + return env_; + } + + /** + * string env = 1; + */ + public com.google.protobuf.ByteString getEnvBytes() { + return ByteString.copyFromUtf8(env_); + } + + /** + * string env = 1; + */ + public Builder setEnv(String value) { + Objects.requireNonNull(value, "Env can not be null"); + + env_ = value; + onChanged(); + return this; + } + + /** + * string env = 1; + */ + public Builder clearEnv() { + env_ = getDefaultInstance().getEnv(); + onChanged(); + return this; + } + + /** + * string env = 1; + */ + public Builder setEnvBytes(com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "EnvBytes can not be null"); + checkByteStringIsUtf8(value); + + env_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String region_ = ""; + + /** + * string region = 2; + */ + public String getRegion() { + return region_; + } + + /** + * string region = 2; + */ + public com.google.protobuf.ByteString getRegionBytes() { + return ByteString.copyFromUtf8(region_); + } + + /** + * string region = 2; + */ + public Builder setRegion( + String value) { + Objects.requireNonNull(value, "Region can not be null"); + + region_ = value; + onChanged(); + return this; + } + + /** + * string region = 2; + */ + public Builder clearRegion() { + + region_ = getDefaultInstance().getRegion(); + onChanged(); + return this; + } + + /** + * string region = 2; + */ + public Builder setRegionBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "RegionBytes can not be null"); + checkByteStringIsUtf8(value); + + region_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String idc_ = ""; + + /** + * string idc = 3; + */ + public String getIdc() { + return idc_; + } + + /** + * string idc = 3; + */ + public com.google.protobuf.ByteString getIdcBytes() { + return ByteString.copyFromUtf8(idc_); + } + + /** + * string idc = 3; + */ + public Builder setIdc(String value) { + Objects.requireNonNull(value, "Idc can not be null"); + + idc_ = value; + onChanged(); + return this; + } + + /** + * string idc = 3; + */ + public Builder clearIdc() { + + idc_ = getDefaultInstance().getIdc(); + onChanged(); + return this; + } + + /** + * string idc = 3; + */ + public Builder setIdcBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "IdcBytes can not be null"); + checkByteStringIsUtf8(value); + + idc_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String ip_ = ""; + + /** + * string ip = 4; + */ + public String getIp() { + return ip_; + } + + /** + * string ip = 4; + */ + public com.google.protobuf.ByteString getIpBytes() { + return ByteString.copyFromUtf8(ip_); + } + + /** + * string ip = 4; + */ + public Builder setIp(String value) { + Objects.requireNonNull(value, "Ip can not be null"); + + ip_ = value; + onChanged(); + return this; + } + + /** + * string ip = 4; + */ + public Builder clearIp() { + + ip_ = getDefaultInstance().getIp(); + onChanged(); + return this; + } + + /** + * string ip = 4; + */ + public Builder setIpBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "IpBytes can not be null"); + checkByteStringIsUtf8(value); + + ip_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String pid_ = ""; + + /** + * string pid = 5; + */ + public String getPid() { + return pid_; + } + + /** + * string pid = 5; + */ + public com.google.protobuf.ByteString getPidBytes() { + return ByteString.copyFromUtf8(pid_); + } + + /** + * string pid = 5; + */ + public Builder setPid( + String value) { + Objects.requireNonNull(value, "Pid can not be null"); + + pid_ = value; + onChanged(); + return this; + } + + /** + * string pid = 5; + */ + public Builder clearPid() { + + pid_ = getDefaultInstance().getPid(); + onChanged(); + return this; + } + + /** + * string pid = 5; + */ + public Builder setPidBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "PidBytes can not be null"); + checkByteStringIsUtf8(value); + + pid_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String sys_ = ""; + + /** + * string sys = 6; + */ + public String getSys() { + return sys_; + } + + /** + * string sys = 6; + */ + public com.google.protobuf.ByteString getSysBytes() { + return ByteString.copyFromUtf8(sys_); + } + + /** + * string sys = 6; + */ + public Builder setSys( + String value) { + Objects.requireNonNull(value, "Sys can not be null"); + + sys_ = value; + onChanged(); + return this; + } + + /** + * string sys = 6; + */ + public Builder clearSys() { + + sys_ = getDefaultInstance().getSys(); + onChanged(); + return this; + } + + /** + * string sys = 6; + */ + public Builder setSysBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "SysBytes can not be null"); + checkByteStringIsUtf8(value); + + sys_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String username_ = ""; + + /** + * string username = 7; + */ + public String getUsername() { + return username_; + } + + /** + * string username = 7; + */ + public com.google.protobuf.ByteString + getUsernameBytes() { + return ByteString.copyFromUtf8(username_); + } + + /** + * string username = 7; + */ + public Builder setUsername( + String value) { + Objects.requireNonNull(value, "Username can not be null"); + + username_ = value; + onChanged(); + return this; + } + + /** + * string username = 7; + */ + public Builder clearUsername() { + + username_ = getDefaultInstance().getUsername(); + onChanged(); + return this; + } + + /** + * string username = 7; + */ + public Builder setUsernameBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "UsernameBytes can not be null"); + checkByteStringIsUtf8(value); + + username_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String password_ = ""; + + /** + * string password = 8; + */ + public String getPassword() { + return password_; + + } + + /** + * string password = 8; + */ + public com.google.protobuf.ByteString getPasswordBytes() { + return ByteString.copyFromUtf8(password_); + } + + /** + * string password = 8; + */ + public Builder setPassword( + String value) { + Objects.requireNonNull(value, "Password can not be null"); + + password_ = value; + onChanged(); + return this; + } + + /** + * string password = 8; + */ + public Builder clearPassword() { + + password_ = getDefaultInstance().getPassword(); + onChanged(); + return this; + } + + /** + * string password = 8; + */ + public Builder setPasswordBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "PasswordBytes can not be null"); + + checkByteStringIsUtf8(value); + + password_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String language_ = ""; + + /** + * string language = 9; + */ + public String getLanguage() { + return language_; + } + + /** + * string language = 9; + */ + public com.google.protobuf.ByteString + getLanguageBytes() { + return ByteString.copyFromUtf8(language_); + } + + /** + * string language = 9; + */ + public Builder setLanguage( + String value) { + Objects.requireNonNull(value, "Language can not be null"); + + language_ = value; + onChanged(); + return this; + } + + /** + * string language = 9; + */ + public Builder clearLanguage() { + + language_ = getDefaultInstance().getLanguage(); + onChanged(); + return this; + } + + /** + * string language = 9; + */ + public Builder setLanguageBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "LanguageBytes can not be null"); + checkByteStringIsUtf8(value); + + language_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String protocolType_ = ""; + + /** + * string protocolType = 10; + */ + public String getProtocolType() { + return protocolType_; + } + + /** + * string protocolType = 10; + */ + public com.google.protobuf.ByteString + getProtocolTypeBytes() { + return ByteString.copyFromUtf8(protocolType_); + } + + /** + * string protocolType = 10; + */ + public Builder setProtocolType( + String value) { + Objects.requireNonNull(value, "ProtocolType can not be null"); + + protocolType_ = value; + onChanged(); + return this; + } + + /** + * string protocolType = 10; + */ + public Builder clearProtocolType() { + + protocolType_ = getDefaultInstance().getProtocolType(); + onChanged(); + return this; + } + + /** + * string protocolType = 10; + */ + public Builder setProtocolTypeBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "ProtocolTypeBytes can not be null"); + checkByteStringIsUtf8(value); + + protocolType_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String protocolVersion_ = ""; + + /** + * string protocolVersion = 11; + */ + public String getProtocolVersion() { + return protocolVersion_; + } + + /** + * string protocolVersion = 11; + */ + public com.google.protobuf.ByteString + getProtocolVersionBytes() { + return ByteString.copyFromUtf8(protocolVersion_); + } + + /** + * string protocolVersion = 11; + */ + public Builder setProtocolVersion( + String value) { + Objects.requireNonNull(value, "ProtocolVersion can not be null"); + + protocolVersion_ = value; + onChanged(); + return this; + } + + /** + * string protocolVersion = 11; + */ + public Builder clearProtocolVersion() { + + protocolVersion_ = getDefaultInstance().getProtocolVersion(); + onChanged(); + return this; + } + + /** + * string protocolVersion = 11; + */ + public Builder setProtocolVersionBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "ProtocolVersionBytes can not be null"); + checkByteStringIsUtf8(value); + + protocolVersion_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String protocolDesc_ = ""; + + /** + * string protocolDesc = 12; + */ + public String getProtocolDesc() { + return protocolDesc_; + } + + /** + * string protocolDesc = 12; + */ + public com.google.protobuf.ByteString getProtocolDescBytes() { + return ByteString.copyFromUtf8(protocolDesc_); + } + + /** + * string protocolDesc = 12; + */ + public Builder setProtocolDesc( + String value) { + Objects.requireNonNull(value, "ProtocolDesc can not be null"); + + protocolDesc_ = value; + onChanged(); + return this; + } + + /** + * string protocolDesc = 12; + */ + public Builder clearProtocolDesc() { + + protocolDesc_ = getDefaultInstance().getProtocolDesc(); + onChanged(); + return this; + } + + /** + * string protocolDesc = 12; + */ + public Builder setProtocolDescBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "ProtocolDescBytes can not be null"); + checkByteStringIsUtf8(value); + + protocolDesc_ = value.toStringUtf8(); + onChanged(); + return this; + } + + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFieldsProto3(unknownFields); + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.common.protocol.grpc.RequestHeader) + } + + // @@protoc_insertion_point(class_scope:eventmesh.common.protocol.grpc.RequestHeader) + private static final RequestHeader DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new RequestHeader(); + } + + public static RequestHeader getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public RequestHeader parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new RequestHeader(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public RequestHeader getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/RequestHeaderOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/RequestHeaderOrBuilder.java new file mode 100644 index 0000000000..ec8a176bba --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/RequestHeaderOrBuilder.java @@ -0,0 +1,147 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +@SuppressWarnings({"all"}) +public interface RequestHeaderOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.common.protocol.grpc.RequestHeader) + com.google.protobuf.MessageOrBuilder { + + /** + * string env = 1; + */ + String getEnv(); + /** + * string env = 1; + */ + com.google.protobuf.ByteString + getEnvBytes(); + + /** + * string region = 2; + */ + String getRegion(); + /** + * string region = 2; + */ + com.google.protobuf.ByteString + getRegionBytes(); + + /** + * string idc = 3; + */ + String getIdc(); + /** + * string idc = 3; + */ + com.google.protobuf.ByteString + getIdcBytes(); + + /** + * string ip = 4; + */ + String getIp(); + /** + * string ip = 4; + */ + com.google.protobuf.ByteString + getIpBytes(); + + /** + * string pid = 5; + */ + String getPid(); + /** + * string pid = 5; + */ + com.google.protobuf.ByteString + getPidBytes(); + + /** + * string sys = 6; + */ + String getSys(); + /** + * string sys = 6; + */ + com.google.protobuf.ByteString + getSysBytes(); + + /** + * string username = 7; + */ + String getUsername(); + /** + * string username = 7; + */ + com.google.protobuf.ByteString + getUsernameBytes(); + + /** + * string password = 8; + */ + String getPassword(); + /** + * string password = 8; + */ + com.google.protobuf.ByteString + getPasswordBytes(); + + /** + * string language = 9; + */ + String getLanguage(); + /** + * string language = 9; + */ + com.google.protobuf.ByteString + getLanguageBytes(); + + /** + * string protocolType = 10; + */ + String getProtocolType(); + /** + * string protocolType = 10; + */ + com.google.protobuf.ByteString + getProtocolTypeBytes(); + + /** + * string protocolVersion = 11; + */ + String getProtocolVersion(); + /** + * string protocolVersion = 11; + */ + com.google.protobuf.ByteString + getProtocolVersionBytes(); + + /** + * string protocolDesc = 12; + */ + String getProtocolDesc(); + /** + * string protocolDesc = 12; + */ + com.google.protobuf.ByteString + getProtocolDescBytes(); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/Response.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/Response.java new file mode 100644 index 0000000000..e5d810663d --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/Response.java @@ -0,0 +1,701 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +import java.util.Objects; + +import com.google.protobuf.ByteString; + +/** + * Protobuf type {@code eventmesh.common.protocol.grpc.Response} + */ +@SuppressWarnings({"all"}) +public final class Response extends com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.common.protocol.grpc.Response) + ResponseOrBuilder { + private static final long serialVersionUID = -6326489945644944331L; + + // Use Response.newBuilder() to construct. + private Response(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private Response() { + respCode_ = ""; + respMsg_ = ""; + respTime_ = ""; + } + + @Override + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { + return this.unknownFields; + } + + private Response( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + Objects.requireNonNull(input,"CodedInputStream can not be null"); + Objects.requireNonNull(extensionRegistry,"ExtensionRegistryLite can not be null"); + + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownFieldProto3( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + respCode_ = input.readStringRequireUtf8(); + break; + } + case 18: { + respMsg_ = input.readStringRequireUtf8(); + break; + } + case 26: { + respTime_ = input.readStringRequireUtf8(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Response_descriptor; + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Response_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Response.class, Builder.class); + } + + public static final int RESPCODE_FIELD_NUMBER = 1; + private volatile String respCode_; + + /** + * string respCode = 1; + */ + public String getRespCode() { + return respCode_; + } + + /** + * string respCode = 1; + */ + public com.google.protobuf.ByteString getRespCodeBytes() { + return ByteString.copyFromUtf8(respCode_); + } + + public static final int RESPMSG_FIELD_NUMBER = 2; + private volatile String respMsg_; + + /** + * string respMsg = 2; + */ + public String getRespMsg() { + return respMsg_; + } + + /** + * string respMsg = 2; + */ + public com.google.protobuf.ByteString getRespMsgBytes() { + return ByteString.copyFromUtf8(respMsg_); + } + + public static final int RESPTIME_FIELD_NUMBER = 3; + private volatile String respTime_; + + /** + * string respTime = 3; + */ + public String getRespTime() { + return respTime_; + } + + /** + * string respTime = 3; + */ + public com.google.protobuf.ByteString getRespTimeBytes() { + return ByteString.copyFromUtf8(respTime_); + } + + private byte memoizedIsInitialized = -1; + + public final boolean isInitialized() { + if (memoizedIsInitialized == 1) return true; + if (memoizedIsInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getRespCodeBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, respCode_); + } + if (!getRespMsgBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, respMsg_); + } + if (!getRespTimeBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, respTime_); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getRespCodeBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, respCode_); + } + if (!getRespMsgBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, respMsg_); + } + if (!getRespTimeBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, respTime_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Response)) { + return super.equals(obj); + } + Response other = (Response) obj; + + return getRespCode().equals(other.getRespCode()) + && getRespMsg().equals(other.getRespMsg()) + && getRespTime().equals(other.getRespTime()) + && unknownFields.equals(other.unknownFields); + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + RESPCODE_FIELD_NUMBER; + hash = (53 * hash) + getRespCode().hashCode(); + hash = (37 * hash) + RESPMSG_FIELD_NUMBER; + hash = (53 * hash) + getRespMsg().hashCode(); + hash = (37 * hash) + RESPTIME_FIELD_NUMBER; + hash = (53 * hash) + getRespTime().hashCode(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static Response parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static Response parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static Response parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static Response parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static Response parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static Response parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static Response parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static Response parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static Response parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static Response parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static Response parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static Response parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(Response prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType(BuilderParent parent) { + return new Builder(parent); + } + + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.Response} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.common.protocol.grpc.Response) + ResponseOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Response_descriptor; + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Response_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Response.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.grpc.protos.Response.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + + public Builder clear() { + super.clear(); + respCode_ = ""; + + respMsg_ = ""; + + respTime_ = ""; + + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Response_descriptor; + } + + public Response getDefaultInstanceForType() { + return Response.getDefaultInstance(); + } + + public Response build() { + Response result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public Response buildPartial() { + Response result = new Response(this); + result.respCode_ = respCode_; + result.respMsg_ = respMsg_; + result.respTime_ = respTime_; + onBuilt(); + return result; + } + + public Builder clone() { + return (Builder) super.clone(); + } + + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.setField(field, value); + } + + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return (Builder) super.clearField(field); + } + + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return (Builder) super.clearOneof(oneof); + } + + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return (Builder) super.setRepeatedField(field, index, value); + } + + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.addRepeatedField(field, value); + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof Response) { + return mergeFrom((Response) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(Response other) { + if (other == Response.getDefaultInstance()) return this; + if (!other.getRespCode().isEmpty()) { + respCode_ = other.respCode_; + onChanged(); + } + if (!other.getRespMsg().isEmpty()) { + respMsg_ = other.respMsg_; + onChanged(); + } + if (!other.getRespTime().isEmpty()) { + respTime_ = other.respTime_; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Response parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (Response) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private String respCode_ = ""; + + /** + * string respCode = 1; + */ + public String getRespCode() { + return respCode_; + } + + /** + * string respCode = 1; + */ + public com.google.protobuf.ByteString + getRespCodeBytes() { + return ByteString.copyFromUtf8(respCode_); + } + + /** + * string respCode = 1; + */ + public Builder setRespCode(String value) { + Objects.requireNonNull(value,"RespCode can not be null"); + + respCode_ = value; + onChanged(); + return this; + } + + /** + * string respCode = 1; + */ + public Builder clearRespCode() { + respCode_ = getDefaultInstance().getRespCode(); + onChanged(); + return this; + } + + /** + * string respCode = 1; + */ + public Builder setRespCodeBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value,"RespCodeBytes can not be null"); + checkByteStringIsUtf8(value); + + respCode_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String respMsg_ = ""; + + /** + * string respMsg = 2; + */ + public String getRespMsg() { + return respMsg_; + } + + /** + * string respMsg = 2; + */ + public com.google.protobuf.ByteString getRespMsgBytes() { + return ByteString.copyFromUtf8(respMsg_); + } + + /** + * string respMsg = 2; + */ + public Builder setRespMsg(String value) { + Objects.requireNonNull(value,"RespMsg can not be null"); + + respMsg_ = value; + onChanged(); + return this; + } + + /** + * string respMsg = 2; + */ + public Builder clearRespMsg() { + + respMsg_ = getDefaultInstance().getRespMsg(); + onChanged(); + return this; + } + + /** + * string respMsg = 2; + */ + public Builder setRespMsgBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value,"RespMsgBytes can not be null"); + checkByteStringIsUtf8(value); + + respMsg_ = value.toStringUtf8(); + onChanged(); + return this; + } + + private String respTime_ = ""; + + /** + * string respTime = 3; + */ + public String getRespTime() { + return respTime_; + } + + /** + * string respTime = 3; + */ + public com.google.protobuf.ByteString getRespTimeBytes() { + return ByteString.copyFromUtf8(respTime_); + } + + /** + * string respTime = 3; + */ + public Builder setRespTime( + String value) { + Objects.requireNonNull(value,"RespTime can not be null"); + + respTime_ = value; + onChanged(); + return this; + } + + /** + * string respTime = 3; + */ + public Builder clearRespTime() { + + respTime_ = getDefaultInstance().getRespTime(); + onChanged(); + return this; + } + + /** + * string respTime = 3; + */ + public Builder setRespTimeBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value,"RespTimeBytes can not be null"); + checkByteStringIsUtf8(value); + + respTime_ = value.toStringUtf8(); + onChanged(); + return this; + } + + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFieldsProto3(unknownFields); + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.common.protocol.grpc.Response) + } + + // @@protoc_insertion_point(class_scope:eventmesh.common.protocol.grpc.Response) + private static final Response DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new Response(); + } + + public static Response getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public Response parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Response(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public Response getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/ResponseOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/ResponseOrBuilder.java new file mode 100644 index 0000000000..9ffcff9482 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/ResponseOrBuilder.java @@ -0,0 +1,57 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +@SuppressWarnings({"all"}) +public interface ResponseOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.common.protocol.grpc.Response) + com.google.protobuf.MessageOrBuilder { + + /** + * string respCode = 1; + */ + String getRespCode(); + /** + * string respCode = 1; + */ + com.google.protobuf.ByteString + getRespCodeBytes(); + + /** + * string respMsg = 2; + */ + String getRespMsg(); + /** + * string respMsg = 2; + */ + com.google.protobuf.ByteString + getRespMsgBytes(); + + /** + * string respTime = 3; + */ + String getRespTime(); + /** + * string respTime = 3; + */ + com.google.protobuf.ByteString + getRespTimeBytes(); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/SimpleMessage.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/SimpleMessage.java new file mode 100644 index 0000000000..70d7518a01 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/SimpleMessage.java @@ -0,0 +1,1802 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +import java.util.Objects; + +/** + * Protobuf type {@code eventmesh.common.protocol.grpc.SimpleMessage} + */ +@SuppressWarnings({"all"}) +public final class SimpleMessage extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.common.protocol.grpc.SimpleMessage) + SimpleMessageOrBuilder { + private static final long serialVersionUID = -6684279788270319330L; + + // Use SimpleMessage.newBuilder() to construct. + private SimpleMessage(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private SimpleMessage() { + producerGroup_ = ""; + topic_ = ""; + content_ = ""; + ttl_ = ""; + uniqueId_ = ""; + seqNum_ = ""; + tag_ = ""; + } + + @Override + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { + return this.unknownFields; + } + + private SimpleMessage(com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownFieldProto3( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + RequestHeader.Builder subBuilder = null; + if (header_ != null) { + subBuilder = header_.toBuilder(); + } + header_ = input.readMessage(RequestHeader.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(header_); + header_ = subBuilder.buildPartial(); + } + + break; + } + case 18: { + producerGroup_ = input.readStringRequireUtf8(); + break; + } + case 26: { + topic_ = input.readStringRequireUtf8(); + break; + } + case 34: { + content_ = input.readStringRequireUtf8(); + break; + } + case 42: { + ttl_ = input.readStringRequireUtf8(); + break; + } + case 50: { + uniqueId_ = input.readStringRequireUtf8(); + break; + } + case 58: { + seqNum_ = input.readStringRequireUtf8(); + break; + } + case 66: { + tag_ = input.readStringRequireUtf8(); + break; + } + case 74: { + if (!((mutable_bitField0_ & 0x00000100) == 0x00000100)) { + properties_ = com.google.protobuf.MapField.newMapField( + PropertiesDefaultEntryHolder.defaultEntry); + mutable_bitField0_ |= 0x00000100; + } + com.google.protobuf.MapEntry + properties__ = input.readMessage( + PropertiesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + properties_.getMutableMap().put( + properties__.getKey(), properties__.getValue()); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_SimpleMessage_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMapField(int number) { + switch (number) { + case 9: + return internalGetProperties(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + + protected FieldAccessorTable internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_SimpleMessage_fieldAccessorTable + .ensureFieldAccessorsInitialized( + SimpleMessage.class, Builder.class); + } + + private int bitField0_; + public static final int HEADER_FIELD_NUMBER = 1; + private RequestHeader header_; + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public boolean hasHeader() { + return header_ != null; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeader getHeader() { + return header_ == null ? RequestHeader.getDefaultInstance() : header_; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeaderOrBuilder getHeaderOrBuilder() { + return getHeader(); + } + + public static final int PRODUCERGROUP_FIELD_NUMBER = 2; + private volatile Object producerGroup_; + + /** + * string producerGroup = 2; + */ + public String getProducerGroup() { + Object ref = producerGroup_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + producerGroup_ = s; + return s; + } + } + + /** + * string producerGroup = 2; + */ + public com.google.protobuf.ByteString + getProducerGroupBytes() { + Object ref = producerGroup_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + producerGroup_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TOPIC_FIELD_NUMBER = 3; + private volatile Object topic_; + + /** + * string topic = 3; + */ + public String getTopic() { + Object ref = topic_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + topic_ = s; + return s; + } + } + + /** + * string topic = 3; + */ + public com.google.protobuf.ByteString + getTopicBytes() { + Object ref = topic_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + topic_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int CONTENT_FIELD_NUMBER = 4; + private volatile Object content_; + + /** + * string content = 4; + */ + public String getContent() { + Object ref = content_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + content_ = s; + return s; + } + } + + /** + * string content = 4; + */ + public com.google.protobuf.ByteString + getContentBytes() { + Object ref = content_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + content_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TTL_FIELD_NUMBER = 5; + private volatile Object ttl_; + + /** + * string ttl = 5; + */ + public String getTtl() { + Object ref = ttl_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + ttl_ = s; + return s; + } + } + + /** + * string ttl = 5; + */ + public com.google.protobuf.ByteString + getTtlBytes() { + Object ref = ttl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + ttl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int UNIQUEID_FIELD_NUMBER = 6; + private volatile Object uniqueId_; + + /** + * string uniqueId = 6; + */ + public String getUniqueId() { + Object ref = uniqueId_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + uniqueId_ = s; + return s; + } + } + + /** + * string uniqueId = 6; + */ + public com.google.protobuf.ByteString + getUniqueIdBytes() { + Object ref = uniqueId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + uniqueId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SEQNUM_FIELD_NUMBER = 7; + private volatile Object seqNum_; + + /** + * string seqNum = 7; + */ + public String getSeqNum() { + Object ref = seqNum_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + seqNum_ = s; + return s; + } + } + + /** + * string seqNum = 7; + */ + public com.google.protobuf.ByteString + getSeqNumBytes() { + Object ref = seqNum_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + seqNum_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TAG_FIELD_NUMBER = 8; + private volatile Object tag_; + + /** + * string tag = 8; + */ + public String getTag() { + Object ref = tag_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + tag_ = s; + return s; + } + } + + /** + * string tag = 8; + */ + public com.google.protobuf.ByteString + getTagBytes() { + Object ref = tag_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + tag_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PROPERTIES_FIELD_NUMBER = 9; + + private static final class PropertiesDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + String, String> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_SimpleMessage_PropertiesEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.STRING, + ""); + } + + private com.google.protobuf.MapField< + String, String> properties_; + + private com.google.protobuf.MapField + internalGetProperties() { + if (properties_ == null) { + return com.google.protobuf.MapField.emptyMapField( + PropertiesDefaultEntryHolder.defaultEntry); + } + return properties_; + } + + public int getPropertiesCount() { + return internalGetProperties().getMap().size(); + } + + /** + * map<string, string> properties = 9; + */ + + public boolean containsProperties(String key) { + Objects.requireNonNull(key, "key can not be null"); + return internalGetProperties().getMap().containsKey(key); + } + + /** + * Use {@link #getPropertiesMap()} instead. + */ + @Deprecated + public java.util.Map getProperties() { + return getPropertiesMap(); + } + + /** + * map<string, string> properties = 9; + */ + + public java.util.Map getPropertiesMap() { + return internalGetProperties().getMap(); + } + + /** + * map<string, string> properties = 9; + */ + + public String getPropertiesOrDefault( + String key, + String defaultValue) { + Objects.requireNonNull(key, "key can not be null"); + + java.util.Map map = + internalGetProperties().getMap(); + String value = map.get(key); + if (value == null) return defaultValue; + return value; + } + + /** + * map<string, string> properties = 9; + */ + + public String getPropertiesOrThrow( + String key) { + Objects.requireNonNull(key, "key can not be null"); + + java.util.Map map = internalGetProperties().getMap(); + + if (!map.containsKey(key)) { + throw new IllegalArgumentException(); + } + return map.get(key); + } + + private byte memoizedIsInitialized = -1; + + public final boolean isInitialized() { + if (memoizedIsInitialized == 1) return true; + if (memoizedIsInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (header_ != null) { + output.writeMessage(1, getHeader()); + } + if (!getProducerGroupBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, producerGroup_); + } + if (!getTopicBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, topic_); + } + if (!getContentBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 4, content_); + } + if (!getTtlBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 5, ttl_); + } + if (!getUniqueIdBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 6, uniqueId_); + } + if (!getSeqNumBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 7, seqNum_); + } + if (!getTagBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 8, tag_); + } + com.google.protobuf.GeneratedMessageV3 + .serializeStringMapTo( + output, + internalGetProperties(), + PropertiesDefaultEntryHolder.defaultEntry, + 9); + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (header_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, getHeader()); + } + if (!getProducerGroupBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, producerGroup_); + } + if (!getTopicBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, topic_); + } + if (!getContentBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, content_); + } + if (!getTtlBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(5, ttl_); + } + if (!getUniqueIdBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(6, uniqueId_); + } + if (!getSeqNumBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(7, seqNum_); + } + if (!getTagBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(8, tag_); + } + for (java.util.Map.Entry entry + : internalGetProperties().getMap().entrySet()) { + com.google.protobuf.MapEntry + properties__ = PropertiesDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(9, properties__); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof SimpleMessage)) { + return super.equals(obj); + } + + SimpleMessage other = (SimpleMessage) obj; + return (hasHeader() ? other.hasHeader() && getHeader().equals(other.getHeader()) : !other.hasHeader()) + && getProducerGroup().equals(other.getProducerGroup()) + && getTopic().equals(other.getTopic()) + && getContent().equals(other.getContent()) + && getTtl().equals(other.getTtl()) + && getUniqueId().equals(other.getUniqueId()) + && getSeqNum().equals(other.getSeqNum()) + && getTag().equals(other.getTag()) + && internalGetProperties().equals(other.internalGetProperties()) + && unknownFields.equals(other.unknownFields); + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasHeader()) { + hash = (37 * hash) + HEADER_FIELD_NUMBER; + hash = (53 * hash) + getHeader().hashCode(); + } + hash = (37 * hash) + PRODUCERGROUP_FIELD_NUMBER; + hash = (53 * hash) + getProducerGroup().hashCode(); + hash = (37 * hash) + TOPIC_FIELD_NUMBER; + hash = (53 * hash) + getTopic().hashCode(); + hash = (37 * hash) + CONTENT_FIELD_NUMBER; + hash = (53 * hash) + getContent().hashCode(); + hash = (37 * hash) + TTL_FIELD_NUMBER; + hash = (53 * hash) + getTtl().hashCode(); + hash = (37 * hash) + UNIQUEID_FIELD_NUMBER; + hash = (53 * hash) + getUniqueId().hashCode(); + hash = (37 * hash) + SEQNUM_FIELD_NUMBER; + hash = (53 * hash) + getSeqNum().hashCode(); + hash = (37 * hash) + TAG_FIELD_NUMBER; + hash = (53 * hash) + getTag().hashCode(); + if (!internalGetProperties().getMap().isEmpty()) { + hash = (37 * hash) + PROPERTIES_FIELD_NUMBER; + hash = (53 * hash) + internalGetProperties().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static SimpleMessage parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static SimpleMessage parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static SimpleMessage parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static SimpleMessage parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static SimpleMessage parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static SimpleMessage parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static SimpleMessage parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static SimpleMessage parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static SimpleMessage parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static SimpleMessage parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static SimpleMessage parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static SimpleMessage parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(SimpleMessage prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + return new Builder(parent); + } + + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.SimpleMessage} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.common.protocol.grpc.SimpleMessage) + SimpleMessageOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_SimpleMessage_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMapField( + int number) { + switch (number) { + case 9: + return internalGetProperties(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMutableMapField( + int number) { + switch (number) { + case 9: + return internalGetMutableProperties(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_SimpleMessage_fieldAccessorTable + .ensureFieldAccessorsInitialized( + SimpleMessage.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.grpc.protos.SimpleMessage.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + + public Builder clear() { + super.clear(); + if (headerBuilder_ == null) { + header_ = null; + } else { + header_ = null; + headerBuilder_ = null; + } + producerGroup_ = ""; + + topic_ = ""; + + content_ = ""; + + ttl_ = ""; + + uniqueId_ = ""; + + seqNum_ = ""; + + tag_ = ""; + + internalGetMutableProperties().clear(); + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_SimpleMessage_descriptor; + } + + public SimpleMessage getDefaultInstanceForType() { + return SimpleMessage.getDefaultInstance(); + } + + public SimpleMessage build() { + SimpleMessage result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public SimpleMessage buildPartial() { + SimpleMessage result = new SimpleMessage(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (headerBuilder_ == null) { + result.header_ = header_; + } else { + result.header_ = headerBuilder_.build(); + } + result.producerGroup_ = producerGroup_; + result.topic_ = topic_; + result.content_ = content_; + result.ttl_ = ttl_; + result.uniqueId_ = uniqueId_; + result.seqNum_ = seqNum_; + result.tag_ = tag_; + result.properties_ = internalGetProperties(); + result.properties_.makeImmutable(); + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder clone() { + return (Builder) super.clone(); + } + + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.setField(field, value); + } + + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return (Builder) super.clearField(field); + } + + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return (Builder) super.clearOneof(oneof); + } + + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return (Builder) super.setRepeatedField(field, index, value); + } + + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.addRepeatedField(field, value); + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof SimpleMessage) { + return mergeFrom((SimpleMessage) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(SimpleMessage other) { + if (other == SimpleMessage.getDefaultInstance()) return this; + if (other.hasHeader()) { + mergeHeader(other.getHeader()); + } + if (!other.getProducerGroup().isEmpty()) { + producerGroup_ = other.producerGroup_; + onChanged(); + } + if (!other.getTopic().isEmpty()) { + topic_ = other.topic_; + onChanged(); + } + if (!other.getContent().isEmpty()) { + content_ = other.content_; + onChanged(); + } + if (!other.getTtl().isEmpty()) { + ttl_ = other.ttl_; + onChanged(); + } + if (!other.getUniqueId().isEmpty()) { + uniqueId_ = other.uniqueId_; + onChanged(); + } + if (!other.getSeqNum().isEmpty()) { + seqNum_ = other.seqNum_; + onChanged(); + } + if (!other.getTag().isEmpty()) { + tag_ = other.tag_; + onChanged(); + } + internalGetMutableProperties().mergeFrom( + other.internalGetProperties()); + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + SimpleMessage parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (SimpleMessage) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private int bitField0_; + + private RequestHeader header_ = null; + private com.google.protobuf.SingleFieldBuilderV3< + RequestHeader, RequestHeader.Builder, RequestHeaderOrBuilder> headerBuilder_; + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public boolean hasHeader() { + return headerBuilder_ != null || header_ != null; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeader getHeader() { + if (headerBuilder_ == null) { + return header_ == null ? RequestHeader.getDefaultInstance() : header_; + } else { + return headerBuilder_.getMessage(); + } + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder setHeader(RequestHeader value) { + if (headerBuilder_ == null) { + Objects.requireNonNull(value, "RequestHeader can not be null"); + header_ = value; + onChanged(); + } else { + headerBuilder_.setMessage(value); + } + + return this; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder setHeader( + RequestHeader.Builder builderForValue) { + if (headerBuilder_ == null) { + header_ = builderForValue.build(); + onChanged(); + } else { + headerBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder mergeHeader(RequestHeader value) { + if (headerBuilder_ == null) { + if (header_ != null) { + header_ = RequestHeader.newBuilder(header_).mergeFrom(value).buildPartial(); + } else { + header_ = value; + } + onChanged(); + } else { + headerBuilder_.mergeFrom(value); + } + + return this; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder clearHeader() { + if (headerBuilder_ == null) { + header_ = null; + onChanged(); + } else { + header_ = null; + headerBuilder_ = null; + } + + return this; + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeader.Builder getHeaderBuilder() { + onChanged(); + return getHeaderFieldBuilder().getBuilder(); + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeaderOrBuilder getHeaderOrBuilder() { + if (headerBuilder_ != null) { + return headerBuilder_.getMessageOrBuilder(); + } else { + return header_ == null ? + RequestHeader.getDefaultInstance() : header_; + } + } + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + private com.google.protobuf.SingleFieldBuilderV3< + RequestHeader, RequestHeader.Builder, RequestHeaderOrBuilder> + getHeaderFieldBuilder() { + if (headerBuilder_ == null) { + headerBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + RequestHeader, RequestHeader.Builder, RequestHeaderOrBuilder>( + getHeader(), + getParentForChildren(), + isClean()); + header_ = null; + } + return headerBuilder_; + } + + private Object producerGroup_ = ""; + + /** + * string producerGroup = 2; + */ + public String getProducerGroup() { + Object ref = producerGroup_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + producerGroup_ = s; + return s; + } else { + return (String) ref; + } + } + + /** + * string producerGroup = 2; + */ + public com.google.protobuf.ByteString + getProducerGroupBytes() { + Object ref = producerGroup_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + producerGroup_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * string producerGroup = 2; + */ + public Builder setProducerGroup( + String value) { + Objects.requireNonNull(value, "ProducerGroup can not be null"); + + producerGroup_ = value; + onChanged(); + return this; + } + + /** + * string producerGroup = 2; + */ + public Builder clearProducerGroup() { + + producerGroup_ = getDefaultInstance().getProducerGroup(); + onChanged(); + return this; + } + + /** + * string producerGroup = 2; + */ + public Builder setProducerGroupBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "ProducerGroupBytes can not be null"); + + checkByteStringIsUtf8(value); + + producerGroup_ = value; + onChanged(); + return this; + } + + private Object topic_ = ""; + + /** + * string topic = 3; + */ + public String getTopic() { + Object ref = topic_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + topic_ = s; + return s; + } else { + return (String) ref; + } + } + + /** + * string topic = 3; + */ + public com.google.protobuf.ByteString + getTopicBytes() { + Object ref = topic_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + topic_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * string topic = 3; + */ + public Builder setTopic(String value) { + Objects.requireNonNull(value, "Topic can not be null"); + + topic_ = value; + onChanged(); + return this; + } + + /** + * string topic = 3; + */ + public Builder clearTopic() { + + topic_ = getDefaultInstance().getTopic(); + onChanged(); + return this; + } + + /** + * string topic = 3; + */ + public Builder setTopicBytes(com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "TopicBytes can not be null"); + checkByteStringIsUtf8(value); + + topic_ = value; + onChanged(); + return this; + } + + private Object content_ = ""; + + /** + * string content = 4; + */ + public String getContent() { + Object ref = content_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + content_ = s; + return s; + } else { + return (String) ref; + } + } + + /** + * string content = 4; + */ + public com.google.protobuf.ByteString + getContentBytes() { + Object ref = content_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + content_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * string content = 4; + */ + public Builder setContent(String value) { + Objects.requireNonNull(value, "Content can not be null"); + + content_ = value; + onChanged(); + return this; + } + + /** + * string content = 4; + */ + public Builder clearContent() { + + content_ = getDefaultInstance().getContent(); + onChanged(); + return this; + } + + /** + * string content = 4; + */ + public Builder setContentBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "ContentBytes can not be null"); + + checkByteStringIsUtf8(value); + + content_ = value; + onChanged(); + return this; + } + + private Object ttl_ = ""; + + /** + * string ttl = 5; + */ + public String getTtl() { + Object ref = ttl_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + ttl_ = s; + return s; + } else { + return (String) ref; + } + } + + /** + * string ttl = 5; + */ + public com.google.protobuf.ByteString + getTtlBytes() { + Object ref = ttl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + ttl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * string ttl = 5; + */ + public Builder setTtl(String value) { + Objects.requireNonNull(value, "Ttl can not be null"); + + ttl_ = value; + onChanged(); + return this; + } + + /** + * string ttl = 5; + */ + public Builder clearTtl() { + ttl_ = getDefaultInstance().getTtl(); + onChanged(); + return this; + } + + /** + * string ttl = 5; + */ + public Builder setTtlBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "TtlBytes can not be null"); + + checkByteStringIsUtf8(value); + + ttl_ = value; + onChanged(); + return this; + } + + private Object uniqueId_ = ""; + + /** + * string uniqueId = 6; + */ + public String getUniqueId() { + Object ref = uniqueId_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + uniqueId_ = s; + return s; + } else { + return (String) ref; + } + } + + /** + * string uniqueId = 6; + */ + public com.google.protobuf.ByteString + getUniqueIdBytes() { + Object ref = uniqueId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + uniqueId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * string uniqueId = 6; + */ + public Builder setUniqueId(String value) { + Objects.requireNonNull(value, "UniqueId can not be null"); + + uniqueId_ = value; + onChanged(); + return this; + } + + /** + * string uniqueId = 6; + */ + public Builder clearUniqueId() { + + uniqueId_ = getDefaultInstance().getUniqueId(); + onChanged(); + return this; + } + + /** + * string uniqueId = 6; + */ + public Builder setUniqueIdBytes(com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "UniqueIdBytes can not be null"); + + checkByteStringIsUtf8(value); + + uniqueId_ = value; + onChanged(); + return this; + } + + private Object seqNum_ = ""; + + /** + * string seqNum = 7; + */ + public String getSeqNum() { + Object ref = seqNum_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + seqNum_ = s; + return s; + } else { + return (String) ref; + } + } + + /** + * string seqNum = 7; + */ + public com.google.protobuf.ByteString + getSeqNumBytes() { + Object ref = seqNum_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + seqNum_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * string seqNum = 7; + */ + public Builder setSeqNum(String value) { + Objects.requireNonNull(value, "SeqNum can not be null"); + + seqNum_ = value; + onChanged(); + return this; + } + + /** + * string seqNum = 7; + */ + public Builder clearSeqNum() { + seqNum_ = getDefaultInstance().getSeqNum(); + onChanged(); + return this; + } + + /** + * string seqNum = 7; + */ + public Builder setSeqNumBytes(com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "SeqNumBytes can not be null"); + checkByteStringIsUtf8(value); + + seqNum_ = value; + onChanged(); + return this; + } + + private Object tag_ = ""; + + /** + * string tag = 8; + */ + public String getTag() { + Object ref = tag_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + tag_ = s; + return s; + } else { + return (String) ref; + } + } + + /** + * string tag = 8; + */ + public com.google.protobuf.ByteString getTagBytes() { + Object ref = tag_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + tag_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * string tag = 8; + */ + public Builder setTag(String value) { + Objects.requireNonNull(value, "tag can not be null"); + + tag_ = value; + onChanged(); + return this; + } + + /** + * string tag = 8; + */ + public Builder clearTag() { + tag_ = getDefaultInstance().getTag(); + onChanged(); + return this; + } + + /** + * string tag = 8; + */ + public Builder setTagBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "TagBytes can not be null"); + checkByteStringIsUtf8(value); + + tag_ = value; + onChanged(); + return this; + } + + private com.google.protobuf.MapField< + String, String> properties_; + + private com.google.protobuf.MapField + internalGetProperties() { + if (properties_ == null) { + return com.google.protobuf.MapField.emptyMapField( + PropertiesDefaultEntryHolder.defaultEntry); + } + return properties_; + } + + private com.google.protobuf.MapField + internalGetMutableProperties() { + onChanged(); + ; + if (properties_ == null) { + properties_ = com.google.protobuf.MapField.newMapField( + PropertiesDefaultEntryHolder.defaultEntry); + } + if (!properties_.isMutable()) { + properties_ = properties_.copy(); + } + return properties_; + } + + public int getPropertiesCount() { + return internalGetProperties().getMap().size(); + } + + /** + * map<string, string> properties = 9; + */ + + public boolean containsProperties( + String key) { + Objects.requireNonNull(key, "key can not be null"); + + return internalGetProperties().getMap().containsKey(key); + } + + /** + * Use {@link #getPropertiesMap()} instead. + */ + @Deprecated + public java.util.Map getProperties() { + return getPropertiesMap(); + } + + /** + * map<string, string> properties = 9; + */ + + public java.util.Map getPropertiesMap() { + return internalGetProperties().getMap(); + } + + /** + * map<string, string> properties = 9; + */ + + public String getPropertiesOrDefault( + String key, + String defaultValue) { + Objects.requireNonNull(key, "key can not be null"); + + java.util.Map map = + internalGetProperties().getMap(); + String value = map.get(key); + if (value == null) return defaultValue; + return value; + } + + /** + * map<string, string> properties = 9; + */ + + public String getPropertiesOrThrow(String key) { + Objects.requireNonNull(key, "key can not be null"); + + java.util.Map map = + internalGetProperties().getMap(); + if (!map.containsKey(key)) { + throw new IllegalArgumentException(); + } + return map.get(key); + } + + public Builder clearProperties() { + internalGetMutableProperties().getMutableMap().clear(); + return this; + } + + /** + * map<string, string> properties = 9; + */ + + public Builder removeProperties(String key) { + Objects.requireNonNull(key, "key can not be null"); + + internalGetMutableProperties().getMutableMap().remove(key); + return this; + } + + /** + * Use alternate mutation accessors instead. + */ + @Deprecated + public java.util.Map getMutableProperties() { + return internalGetMutableProperties().getMutableMap(); + } + + /** + * map<string, string> properties = 9; + */ + public Builder putProperties( + String key, + String value) { + if (key == null) { + throw new NullPointerException(); + } + if (value == null) { + throw new NullPointerException(); + } + internalGetMutableProperties().getMutableMap() + .put(key, value); + return this; + } + + /** + * map<string, string> properties = 9; + */ + + public Builder putAllProperties(java.util.Map values) { + internalGetMutableProperties().getMutableMap().putAll(values); + return this; + } + + public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFieldsProto3(unknownFields); + } + + public final Builder mergeUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.common.protocol.grpc.SimpleMessage) + } + + // @@protoc_insertion_point(class_scope:eventmesh.common.protocol.grpc.SimpleMessage) + private static final SimpleMessage DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new SimpleMessage(); + } + + public static SimpleMessage getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + public SimpleMessage parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new SimpleMessage(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public SimpleMessage getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} \ No newline at end of file diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/SimpleMessageOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/SimpleMessageOrBuilder.java new file mode 100644 index 0000000000..dfda9c63ae --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/SimpleMessageOrBuilder.java @@ -0,0 +1,144 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +@SuppressWarnings({"all"}) +public interface SimpleMessageOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.common.protocol.grpc.SimpleMessage) + com.google.protobuf.MessageOrBuilder { + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + boolean hasHeader(); + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + RequestHeader getHeader(); + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + RequestHeaderOrBuilder getHeaderOrBuilder(); + + /** + * string producerGroup = 2; + */ + String getProducerGroup(); + /** + * string producerGroup = 2; + */ + com.google.protobuf.ByteString + getProducerGroupBytes(); + + /** + * string topic = 3; + */ + String getTopic(); + /** + * string topic = 3; + */ + com.google.protobuf.ByteString + getTopicBytes(); + + /** + * string content = 4; + */ + String getContent(); + /** + * string content = 4; + */ + com.google.protobuf.ByteString + getContentBytes(); + + /** + * string ttl = 5; + */ + String getTtl(); + /** + * string ttl = 5; + */ + com.google.protobuf.ByteString + getTtlBytes(); + + /** + * string uniqueId = 6; + */ + String getUniqueId(); + /** + * string uniqueId = 6; + */ + com.google.protobuf.ByteString + getUniqueIdBytes(); + + /** + * string seqNum = 7; + */ + String getSeqNum(); + /** + * string seqNum = 7; + */ + com.google.protobuf.ByteString + getSeqNumBytes(); + + /** + * string tag = 8; + */ + String getTag(); + /** + * string tag = 8; + */ + com.google.protobuf.ByteString + getTagBytes(); + + /** + * map<string, string> properties = 9; + */ + int getPropertiesCount(); + /** + * map<string, string> properties = 9; + */ + boolean containsProperties( + String key); + /** + * Use {@link #getPropertiesMap()} instead. + */ + @Deprecated + java.util.Map + getProperties(); + /** + * map<string, string> properties = 9; + */ + java.util.Map + getPropertiesMap(); + /** + * map<string, string> properties = 9; + */ + + String getPropertiesOrDefault( + String key, + String defaultValue); + /** + * map<string, string> properties = 9; + */ + + String getPropertiesOrThrow( + String key); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/Subscription.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/Subscription.java new file mode 100644 index 0000000000..7b33ff72b4 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/Subscription.java @@ -0,0 +1,3932 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +/** + * Protobuf type {@code eventmesh.common.protocol.grpc.Subscription} + */ +@SuppressWarnings({"all"}) +public final class Subscription extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.common.protocol.grpc.Subscription) + SubscriptionOrBuilder { +private static final long serialVersionUID = 0L; + // Use Subscription.newBuilder() to construct. + private Subscription(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private Subscription() { + consumerGroup_ = ""; + subscriptionItems_ = java.util.Collections.emptyList(); + url_ = ""; + } + + @Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Subscription( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownFieldProto3( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + RequestHeader.Builder subBuilder = null; + if (header_ != null) { + subBuilder = header_.toBuilder(); + } + header_ = input.readMessage(RequestHeader.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(header_); + header_ = subBuilder.buildPartial(); + } + + break; + } + case 18: { + String s = input.readStringRequireUtf8(); + + consumerGroup_ = s; + break; + } + case 26: { + if (!((mutable_bitField0_ & 0x00000004) == 0x00000004)) { + subscriptionItems_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000004; + } + subscriptionItems_.add( + input.readMessage(SubscriptionItem.parser(), extensionRegistry)); + break; + } + case 34: { + String s = input.readStringRequireUtf8(); + + url_ = s; + break; + } + case 42: { + Reply.Builder subBuilder = null; + if (reply_ != null) { + subBuilder = reply_.toBuilder(); + } + reply_ = input.readMessage(Reply.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(reply_); + reply_ = subBuilder.buildPartial(); + } + + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000004) == 0x00000004)) { + subscriptionItems_ = java.util.Collections.unmodifiableList(subscriptionItems_); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_descriptor; + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Subscription.class, Builder.class); + } + + public interface SubscriptionItemOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.common.protocol.grpc.Subscription.SubscriptionItem) + com.google.protobuf.MessageOrBuilder { + + /** + * string topic = 1; + */ + String getTopic(); + /** + * string topic = 1; + */ + com.google.protobuf.ByteString + getTopicBytes(); + + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionMode mode = 2; + */ + int getModeValue(); + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionMode mode = 2; + */ + SubscriptionItem.SubscriptionMode getMode(); + + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionType type = 3; + */ + int getTypeValue(); + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionType type = 3; + */ + SubscriptionItem.SubscriptionType getType(); + } + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.Subscription.SubscriptionItem} + */ + public static final class SubscriptionItem extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.common.protocol.grpc.Subscription.SubscriptionItem) + SubscriptionItemOrBuilder { + private static final long serialVersionUID = 0L; + // Use SubscriptionItem.newBuilder() to construct. + private SubscriptionItem(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private SubscriptionItem() { + topic_ = ""; + mode_ = 0; + type_ = 0; + } + + @Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private SubscriptionItem( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownFieldProto3( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + String s = input.readStringRequireUtf8(); + + topic_ = s; + break; + } + case 16: { + int rawValue = input.readEnum(); + + mode_ = rawValue; + break; + } + case 24: { + int rawValue = input.readEnum(); + + type_ = rawValue; + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_SubscriptionItem_descriptor; + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_SubscriptionItem_fieldAccessorTable + .ensureFieldAccessorsInitialized( + SubscriptionItem.class, Builder.class); + } + + /** + * Protobuf enum {@code eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionMode} + */ + public enum SubscriptionMode + implements com.google.protobuf.ProtocolMessageEnum { + /** + * CLUSTERING = 0; + */ + CLUSTERING(0), + /** + * BROADCASTING = 1; + */ + BROADCASTING(1), + UNRECOGNIZED(-1), + ; + + /** + * CLUSTERING = 0; + */ + public static final int CLUSTERING_VALUE = 0; + /** + * BROADCASTING = 1; + */ + public static final int BROADCASTING_VALUE = 1; + + + public final int getNumber() { + if (this == UNRECOGNIZED) { + throw new IllegalArgumentException( + "Can't get the number of an unknown enum value."); + } + return value; + } + + /** + * @deprecated Use {@link #forNumber(int)} instead. + */ + @Deprecated + public static SubscriptionMode valueOf(int value) { + return forNumber(value); + } + + public static SubscriptionMode forNumber(int value) { + switch (value) { + case 0: return CLUSTERING; + case 1: return BROADCASTING; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static final com.google.protobuf.Internal.EnumLiteMap< + SubscriptionMode> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public SubscriptionMode findValueByNumber(int number) { + return SubscriptionMode.forNumber(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + return getDescriptor().getValues().get(ordinal()); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return SubscriptionItem.getDescriptor().getEnumTypes().get(0); + } + + private static final SubscriptionMode[] VALUES = values(); + + public static SubscriptionMode valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + if (desc.getIndex() == -1) { + return UNRECOGNIZED; + } + return VALUES[desc.getIndex()]; + } + + private final int value; + + private SubscriptionMode(int value) { + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionMode) + } + + /** + * Protobuf enum {@code eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionType} + */ + public enum SubscriptionType + implements com.google.protobuf.ProtocolMessageEnum { + /** + * ASYNC = 0; + */ + ASYNC(0), + /** + * SYNC = 1; + */ + SYNC(1), + UNRECOGNIZED(-1), + ; + + /** + * ASYNC = 0; + */ + public static final int ASYNC_VALUE = 0; + /** + * SYNC = 1; + */ + public static final int SYNC_VALUE = 1; + + + public final int getNumber() { + if (this == UNRECOGNIZED) { + throw new IllegalArgumentException( + "Can't get the number of an unknown enum value."); + } + return value; + } + + /** + * @deprecated Use {@link #forNumber(int)} instead. + */ + @Deprecated + public static SubscriptionType valueOf(int value) { + return forNumber(value); + } + + public static SubscriptionType forNumber(int value) { + switch (value) { + case 0: return ASYNC; + case 1: return SYNC; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static final com.google.protobuf.Internal.EnumLiteMap< + SubscriptionType> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public SubscriptionType findValueByNumber(int number) { + return SubscriptionType.forNumber(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + return getDescriptor().getValues().get(ordinal()); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return SubscriptionItem.getDescriptor().getEnumTypes().get(1); + } + + private static final SubscriptionType[] VALUES = values(); + + public static SubscriptionType valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + if (desc.getIndex() == -1) { + return UNRECOGNIZED; + } + return VALUES[desc.getIndex()]; + } + + private final int value; + + private SubscriptionType(int value) { + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionType) + } + + public static final int TOPIC_FIELD_NUMBER = 1; + private volatile Object topic_; + /** + * string topic = 1; + */ + public String getTopic() { + Object ref = topic_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + topic_ = s; + return s; + } + } + /** + * string topic = 1; + */ + public com.google.protobuf.ByteString + getTopicBytes() { + Object ref = topic_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + topic_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int MODE_FIELD_NUMBER = 2; + private int mode_; + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionMode mode = 2; + */ + public int getModeValue() { + return mode_; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionMode mode = 2; + */ + public SubscriptionMode getMode() { + SubscriptionMode result = SubscriptionMode.valueOf(mode_); + return result == null ? SubscriptionMode.UNRECOGNIZED : result; + } + + public static final int TYPE_FIELD_NUMBER = 3; + private int type_; + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionType type = 3; + */ + public int getTypeValue() { + return type_; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionType type = 3; + */ + public SubscriptionType getType() { + SubscriptionType result = SubscriptionType.valueOf(type_); + return result == null ? SubscriptionType.UNRECOGNIZED : result; + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getTopicBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, topic_); + } + if (mode_ != SubscriptionMode.CLUSTERING.getNumber()) { + output.writeEnum(2, mode_); + } + if (type_ != SubscriptionType.ASYNC.getNumber()) { + output.writeEnum(3, type_); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getTopicBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, topic_); + } + if (mode_ != SubscriptionMode.CLUSTERING.getNumber()) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(2, mode_); + } + if (type_ != SubscriptionType.ASYNC.getNumber()) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(3, type_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof SubscriptionItem)) { + return super.equals(obj); + } + SubscriptionItem other = (SubscriptionItem) obj; + + boolean result = true; + result = result && getTopic() + .equals(other.getTopic()); + result = result && mode_ == other.mode_; + result = result && type_ == other.type_; + return result && unknownFields.equals(other.unknownFields); + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + TOPIC_FIELD_NUMBER; + hash = (53 * hash) + getTopic().hashCode(); + hash = (37 * hash) + MODE_FIELD_NUMBER; + hash = (53 * hash) + mode_; + hash = (37 * hash) + TYPE_FIELD_NUMBER; + hash = (53 * hash) + type_; + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static SubscriptionItem parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static SubscriptionItem parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static SubscriptionItem parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static SubscriptionItem parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static SubscriptionItem parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static SubscriptionItem parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static SubscriptionItem parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static SubscriptionItem parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static SubscriptionItem parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static SubscriptionItem parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static SubscriptionItem parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static SubscriptionItem parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(SubscriptionItem prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + return new Builder(parent); + } + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.Subscription.SubscriptionItem} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.common.protocol.grpc.Subscription.SubscriptionItem) + SubscriptionItemOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_SubscriptionItem_descriptor; + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_SubscriptionItem_fieldAccessorTable + .ensureFieldAccessorsInitialized( + SubscriptionItem.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.grpc.protos.Subscription.SubscriptionItem.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + topic_ = ""; + + mode_ = 0; + + type_ = 0; + + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_SubscriptionItem_descriptor; + } + + public SubscriptionItem getDefaultInstanceForType() { + return SubscriptionItem.getDefaultInstance(); + } + + public SubscriptionItem build() { + SubscriptionItem result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public SubscriptionItem buildPartial() { + SubscriptionItem result = new SubscriptionItem(this); + result.topic_ = topic_; + result.mode_ = mode_; + result.type_ = type_; + onBuilt(); + return result; + } + + public Builder clone() { + return (Builder) super.clone(); + } + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.setField(field, value); + } + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return (Builder) super.clearField(field); + } + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return (Builder) super.clearOneof(oneof); + } + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return (Builder) super.setRepeatedField(field, index, value); + } + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.addRepeatedField(field, value); + } + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof SubscriptionItem) { + return mergeFrom((SubscriptionItem)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(SubscriptionItem other) { + if (other == SubscriptionItem.getDefaultInstance()) return this; + if (!other.getTopic().isEmpty()) { + topic_ = other.topic_; + onChanged(); + } + if (other.mode_ != 0) { + setModeValue(other.getModeValue()); + } + if (other.type_ != 0) { + setTypeValue(other.getTypeValue()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + SubscriptionItem parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (SubscriptionItem) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private Object topic_ = ""; + /** + * string topic = 1; + */ + public String getTopic() { + Object ref = topic_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + topic_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string topic = 1; + */ + public com.google.protobuf.ByteString + getTopicBytes() { + Object ref = topic_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + topic_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string topic = 1; + */ + public Builder setTopic( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + topic_ = value; + onChanged(); + return this; + } + /** + * string topic = 1; + */ + public Builder clearTopic() { + + topic_ = getDefaultInstance().getTopic(); + onChanged(); + return this; + } + /** + * string topic = 1; + */ + public Builder setTopicBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + topic_ = value; + onChanged(); + return this; + } + + private int mode_ = 0; + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionMode mode = 2; + */ + public int getModeValue() { + return mode_; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionMode mode = 2; + */ + public Builder setModeValue(int value) { + mode_ = value; + onChanged(); + return this; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionMode mode = 2; + */ + public SubscriptionMode getMode() { + SubscriptionMode result = SubscriptionMode.valueOf(mode_); + return result == null ? SubscriptionMode.UNRECOGNIZED : result; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionMode mode = 2; + */ + public Builder setMode(SubscriptionMode value) { + if (value == null) { + throw new NullPointerException(); + } + + mode_ = value.getNumber(); + onChanged(); + return this; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionMode mode = 2; + */ + public Builder clearMode() { + + mode_ = 0; + onChanged(); + return this; + } + + private int type_ = 0; + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionType type = 3; + */ + public int getTypeValue() { + return type_; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionType type = 3; + */ + public Builder setTypeValue(int value) { + type_ = value; + onChanged(); + return this; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionType type = 3; + */ + public SubscriptionType getType() { + SubscriptionType result = SubscriptionType.valueOf(type_); + return result == null ? SubscriptionType.UNRECOGNIZED : result; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionType type = 3; + */ + public Builder setType(SubscriptionType value) { + if (value == null) { + throw new NullPointerException(); + } + + type_ = value.getNumber(); + onChanged(); + return this; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem.SubscriptionType type = 3; + */ + public Builder clearType() { + + type_ = 0; + onChanged(); + return this; + } + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFieldsProto3(unknownFields); + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.common.protocol.grpc.Subscription.SubscriptionItem) + } + + // @@protoc_insertion_point(class_scope:eventmesh.common.protocol.grpc.Subscription.SubscriptionItem) + private static final SubscriptionItem DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new SubscriptionItem(); + } + + public static SubscriptionItem getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public SubscriptionItem parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new SubscriptionItem(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public SubscriptionItem getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface ReplyOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.common.protocol.grpc.Subscription.Reply) + com.google.protobuf.MessageOrBuilder { + + /** + * string producerGroup = 1; + */ + String getProducerGroup(); + /** + * string producerGroup = 1; + */ + com.google.protobuf.ByteString + getProducerGroupBytes(); + + /** + * string topic = 2; + */ + String getTopic(); + /** + * string topic = 2; + */ + com.google.protobuf.ByteString + getTopicBytes(); + + /** + * string content = 3; + */ + String getContent(); + /** + * string content = 3; + */ + com.google.protobuf.ByteString + getContentBytes(); + + /** + * string ttl = 4; + */ + String getTtl(); + /** + * string ttl = 4; + */ + com.google.protobuf.ByteString + getTtlBytes(); + + /** + * string uniqueId = 5; + */ + String getUniqueId(); + /** + * string uniqueId = 5; + */ + com.google.protobuf.ByteString + getUniqueIdBytes(); + + /** + * string seqNum = 6; + */ + String getSeqNum(); + /** + * string seqNum = 6; + */ + com.google.protobuf.ByteString + getSeqNumBytes(); + + /** + * string tag = 7; + */ + String getTag(); + /** + * string tag = 7; + */ + com.google.protobuf.ByteString + getTagBytes(); + + /** + * map<string, string> properties = 8; + */ + int getPropertiesCount(); + /** + * map<string, string> properties = 8; + */ + boolean containsProperties( + String key); + /** + * Use {@link #getPropertiesMap()} instead. + */ + @Deprecated + java.util.Map + getProperties(); + /** + * map<string, string> properties = 8; + */ + java.util.Map + getPropertiesMap(); + /** + * map<string, string> properties = 8; + */ + + String getPropertiesOrDefault( + String key, + String defaultValue); + /** + * map<string, string> properties = 8; + */ + + String getPropertiesOrThrow( + String key); + } + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.Subscription.Reply} + */ + public static final class Reply extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.common.protocol.grpc.Subscription.Reply) + ReplyOrBuilder { + private static final long serialVersionUID = 0L; + // Use Reply.newBuilder() to construct. + private Reply(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private Reply() { + producerGroup_ = ""; + topic_ = ""; + content_ = ""; + ttl_ = ""; + uniqueId_ = ""; + seqNum_ = ""; + tag_ = ""; + } + + @Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Reply( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownFieldProto3( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + String s = input.readStringRequireUtf8(); + + producerGroup_ = s; + break; + } + case 18: { + String s = input.readStringRequireUtf8(); + + topic_ = s; + break; + } + case 26: { + String s = input.readStringRequireUtf8(); + + content_ = s; + break; + } + case 34: { + String s = input.readStringRequireUtf8(); + + ttl_ = s; + break; + } + case 42: { + String s = input.readStringRequireUtf8(); + + uniqueId_ = s; + break; + } + case 50: { + String s = input.readStringRequireUtf8(); + + seqNum_ = s; + break; + } + case 58: { + String s = input.readStringRequireUtf8(); + + tag_ = s; + break; + } + case 66: { + if (!((mutable_bitField0_ & 0x00000080) == 0x00000080)) { + properties_ = com.google.protobuf.MapField.newMapField( + PropertiesDefaultEntryHolder.defaultEntry); + mutable_bitField0_ |= 0x00000080; + } + com.google.protobuf.MapEntry + properties__ = input.readMessage( + PropertiesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + properties_.getMutableMap().put( + properties__.getKey(), properties__.getValue()); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMapField( + int number) { + switch (number) { + case 8: + return internalGetProperties(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Reply.class, Builder.class); + } + + private int bitField0_; + public static final int PRODUCERGROUP_FIELD_NUMBER = 1; + private volatile Object producerGroup_; + /** + * string producerGroup = 1; + */ + public String getProducerGroup() { + Object ref = producerGroup_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + producerGroup_ = s; + return s; + } + } + /** + * string producerGroup = 1; + */ + public com.google.protobuf.ByteString + getProducerGroupBytes() { + Object ref = producerGroup_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + producerGroup_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TOPIC_FIELD_NUMBER = 2; + private volatile Object topic_; + /** + * string topic = 2; + */ + public String getTopic() { + Object ref = topic_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + topic_ = s; + return s; + } + } + /** + * string topic = 2; + */ + public com.google.protobuf.ByteString + getTopicBytes() { + Object ref = topic_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + topic_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int CONTENT_FIELD_NUMBER = 3; + private volatile Object content_; + /** + * string content = 3; + */ + public String getContent() { + Object ref = content_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + content_ = s; + return s; + } + } + /** + * string content = 3; + */ + public com.google.protobuf.ByteString + getContentBytes() { + Object ref = content_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + content_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TTL_FIELD_NUMBER = 4; + private volatile Object ttl_; + /** + * string ttl = 4; + */ + public String getTtl() { + Object ref = ttl_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + ttl_ = s; + return s; + } + } + /** + * string ttl = 4; + */ + public com.google.protobuf.ByteString + getTtlBytes() { + Object ref = ttl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + ttl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int UNIQUEID_FIELD_NUMBER = 5; + private volatile Object uniqueId_; + /** + * string uniqueId = 5; + */ + public String getUniqueId() { + Object ref = uniqueId_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + uniqueId_ = s; + return s; + } + } + /** + * string uniqueId = 5; + */ + public com.google.protobuf.ByteString + getUniqueIdBytes() { + Object ref = uniqueId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + uniqueId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SEQNUM_FIELD_NUMBER = 6; + private volatile Object seqNum_; + /** + * string seqNum = 6; + */ + public String getSeqNum() { + Object ref = seqNum_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + seqNum_ = s; + return s; + } + } + /** + * string seqNum = 6; + */ + public com.google.protobuf.ByteString + getSeqNumBytes() { + Object ref = seqNum_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + seqNum_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TAG_FIELD_NUMBER = 7; + private volatile Object tag_; + /** + * string tag = 7; + */ + public String getTag() { + Object ref = tag_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + tag_ = s; + return s; + } + } + /** + * string tag = 7; + */ + public com.google.protobuf.ByteString + getTagBytes() { + Object ref = tag_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + tag_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PROPERTIES_FIELD_NUMBER = 8; + private static final class PropertiesDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + String, String> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_PropertiesEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.STRING, + ""); + } + private com.google.protobuf.MapField< + String, String> properties_; + private com.google.protobuf.MapField + internalGetProperties() { + if (properties_ == null) { + return com.google.protobuf.MapField.emptyMapField( + PropertiesDefaultEntryHolder.defaultEntry); + } + return properties_; + } + + public int getPropertiesCount() { + return internalGetProperties().getMap().size(); + } + /** + * map<string, string> properties = 8; + */ + + public boolean containsProperties( + String key) { + if (key == null) { throw new NullPointerException(); } + return internalGetProperties().getMap().containsKey(key); + } + /** + * Use {@link #getPropertiesMap()} instead. + */ + @Deprecated + public java.util.Map getProperties() { + return getPropertiesMap(); + } + /** + * map<string, string> properties = 8; + */ + + public java.util.Map getPropertiesMap() { + return internalGetProperties().getMap(); + } + /** + * map<string, string> properties = 8; + */ + + public String getPropertiesOrDefault( + String key, + String defaultValue) { + if (key == null) { throw new NullPointerException(); } + java.util.Map map = + internalGetProperties().getMap(); + String value = map.get(key); + if(value == null) return defaultValue; + return value; + } + /** + * map<string, string> properties = 8; + */ + + public String getPropertiesOrThrow( + String key) { + if (key == null) { throw new NullPointerException(); } + java.util.Map map = + internalGetProperties().getMap(); + if (!map.containsKey(key)) { + throw new IllegalArgumentException(); + } + return map.get(key); + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getProducerGroupBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, producerGroup_); + } + if (!getTopicBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, topic_); + } + if (!getContentBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, content_); + } + if (!getTtlBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 4, ttl_); + } + if (!getUniqueIdBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 5, uniqueId_); + } + if (!getSeqNumBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 6, seqNum_); + } + if (!getTagBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 7, tag_); + } + com.google.protobuf.GeneratedMessageV3 + .serializeStringMapTo( + output, + internalGetProperties(), + PropertiesDefaultEntryHolder.defaultEntry, + 8); + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getProducerGroupBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, producerGroup_); + } + if (!getTopicBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, topic_); + } + if (!getContentBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, content_); + } + if (!getTtlBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, ttl_); + } + if (!getUniqueIdBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(5, uniqueId_); + } + if (!getSeqNumBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(6, seqNum_); + } + if (!getTagBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(7, tag_); + } + for (java.util.Map.Entry entry + : internalGetProperties().getMap().entrySet()) { + com.google.protobuf.MapEntry + properties__ = PropertiesDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, properties__); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Reply)) { + return super.equals(obj); + } + Reply other = (Reply) obj; + + boolean result = true; + result = result && getProducerGroup() + .equals(other.getProducerGroup()); + result = result && getTopic() + .equals(other.getTopic()); + result = result && getContent() + .equals(other.getContent()); + result = result && getTtl() + .equals(other.getTtl()); + result = result && getUniqueId() + .equals(other.getUniqueId()); + result = result && getSeqNum() + .equals(other.getSeqNum()); + result = result && getTag() + .equals(other.getTag()); + result = result && internalGetProperties().equals( + other.internalGetProperties()); + return result && unknownFields.equals(other.unknownFields); + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + PRODUCERGROUP_FIELD_NUMBER; + hash = (53 * hash) + getProducerGroup().hashCode(); + hash = (37 * hash) + TOPIC_FIELD_NUMBER; + hash = (53 * hash) + getTopic().hashCode(); + hash = (37 * hash) + CONTENT_FIELD_NUMBER; + hash = (53 * hash) + getContent().hashCode(); + hash = (37 * hash) + TTL_FIELD_NUMBER; + hash = (53 * hash) + getTtl().hashCode(); + hash = (37 * hash) + UNIQUEID_FIELD_NUMBER; + hash = (53 * hash) + getUniqueId().hashCode(); + hash = (37 * hash) + SEQNUM_FIELD_NUMBER; + hash = (53 * hash) + getSeqNum().hashCode(); + hash = (37 * hash) + TAG_FIELD_NUMBER; + hash = (53 * hash) + getTag().hashCode(); + if (!internalGetProperties().getMap().isEmpty()) { + hash = (37 * hash) + PROPERTIES_FIELD_NUMBER; + hash = (53 * hash) + internalGetProperties().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static Reply parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Reply parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Reply parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Reply parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Reply parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Reply parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Reply parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Reply parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static Reply parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static Reply parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static Reply parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Reply parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(Reply prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + return new Builder(parent); + } + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.Subscription.Reply} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.common.protocol.grpc.Subscription.Reply) + ReplyOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMapField( + int number) { + switch (number) { + case 8: + return internalGetProperties(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMutableMapField( + int number) { + switch (number) { + case 8: + return internalGetMutableProperties(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Reply.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.grpc.protos.Subscription.Reply.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + producerGroup_ = ""; + + topic_ = ""; + + content_ = ""; + + ttl_ = ""; + + uniqueId_ = ""; + + seqNum_ = ""; + + tag_ = ""; + + internalGetMutableProperties().clear(); + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_Reply_descriptor; + } + + public Reply getDefaultInstanceForType() { + return Reply.getDefaultInstance(); + } + + public Reply build() { + Reply result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public Reply buildPartial() { + Reply result = new Reply(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + result.producerGroup_ = producerGroup_; + result.topic_ = topic_; + result.content_ = content_; + result.ttl_ = ttl_; + result.uniqueId_ = uniqueId_; + result.seqNum_ = seqNum_; + result.tag_ = tag_; + result.properties_ = internalGetProperties(); + result.properties_.makeImmutable(); + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder clone() { + return (Builder) super.clone(); + } + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.setField(field, value); + } + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return (Builder) super.clearField(field); + } + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return (Builder) super.clearOneof(oneof); + } + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return (Builder) super.setRepeatedField(field, index, value); + } + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.addRepeatedField(field, value); + } + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof Reply) { + return mergeFrom((Reply)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(Reply other) { + if (other == Reply.getDefaultInstance()) return this; + if (!other.getProducerGroup().isEmpty()) { + producerGroup_ = other.producerGroup_; + onChanged(); + } + if (!other.getTopic().isEmpty()) { + topic_ = other.topic_; + onChanged(); + } + if (!other.getContent().isEmpty()) { + content_ = other.content_; + onChanged(); + } + if (!other.getTtl().isEmpty()) { + ttl_ = other.ttl_; + onChanged(); + } + if (!other.getUniqueId().isEmpty()) { + uniqueId_ = other.uniqueId_; + onChanged(); + } + if (!other.getSeqNum().isEmpty()) { + seqNum_ = other.seqNum_; + onChanged(); + } + if (!other.getTag().isEmpty()) { + tag_ = other.tag_; + onChanged(); + } + internalGetMutableProperties().mergeFrom( + other.internalGetProperties()); + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Reply parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (Reply) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private Object producerGroup_ = ""; + /** + * string producerGroup = 1; + */ + public String getProducerGroup() { + Object ref = producerGroup_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + producerGroup_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string producerGroup = 1; + */ + public com.google.protobuf.ByteString + getProducerGroupBytes() { + Object ref = producerGroup_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + producerGroup_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string producerGroup = 1; + */ + public Builder setProducerGroup( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + producerGroup_ = value; + onChanged(); + return this; + } + /** + * string producerGroup = 1; + */ + public Builder clearProducerGroup() { + + producerGroup_ = getDefaultInstance().getProducerGroup(); + onChanged(); + return this; + } + /** + * string producerGroup = 1; + */ + public Builder setProducerGroupBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + producerGroup_ = value; + onChanged(); + return this; + } + + private Object topic_ = ""; + /** + * string topic = 2; + */ + public String getTopic() { + Object ref = topic_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + topic_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string topic = 2; + */ + public com.google.protobuf.ByteString + getTopicBytes() { + Object ref = topic_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + topic_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string topic = 2; + */ + public Builder setTopic( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + topic_ = value; + onChanged(); + return this; + } + /** + * string topic = 2; + */ + public Builder clearTopic() { + + topic_ = getDefaultInstance().getTopic(); + onChanged(); + return this; + } + /** + * string topic = 2; + */ + public Builder setTopicBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + topic_ = value; + onChanged(); + return this; + } + + private Object content_ = ""; + /** + * string content = 3; + */ + public String getContent() { + Object ref = content_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + content_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string content = 3; + */ + public com.google.protobuf.ByteString + getContentBytes() { + Object ref = content_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + content_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string content = 3; + */ + public Builder setContent( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + content_ = value; + onChanged(); + return this; + } + /** + * string content = 3; + */ + public Builder clearContent() { + + content_ = getDefaultInstance().getContent(); + onChanged(); + return this; + } + /** + * string content = 3; + */ + public Builder setContentBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + content_ = value; + onChanged(); + return this; + } + + private Object ttl_ = ""; + /** + * string ttl = 4; + */ + public String getTtl() { + Object ref = ttl_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + ttl_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string ttl = 4; + */ + public com.google.protobuf.ByteString + getTtlBytes() { + Object ref = ttl_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + ttl_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string ttl = 4; + */ + public Builder setTtl( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + ttl_ = value; + onChanged(); + return this; + } + /** + * string ttl = 4; + */ + public Builder clearTtl() { + + ttl_ = getDefaultInstance().getTtl(); + onChanged(); + return this; + } + /** + * string ttl = 4; + */ + public Builder setTtlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + ttl_ = value; + onChanged(); + return this; + } + + private Object uniqueId_ = ""; + /** + * string uniqueId = 5; + */ + public String getUniqueId() { + Object ref = uniqueId_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + uniqueId_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string uniqueId = 5; + */ + public com.google.protobuf.ByteString + getUniqueIdBytes() { + Object ref = uniqueId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + uniqueId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string uniqueId = 5; + */ + public Builder setUniqueId( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + uniqueId_ = value; + onChanged(); + return this; + } + /** + * string uniqueId = 5; + */ + public Builder clearUniqueId() { + + uniqueId_ = getDefaultInstance().getUniqueId(); + onChanged(); + return this; + } + /** + * string uniqueId = 5; + */ + public Builder setUniqueIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + uniqueId_ = value; + onChanged(); + return this; + } + + private Object seqNum_ = ""; + /** + * string seqNum = 6; + */ + public String getSeqNum() { + Object ref = seqNum_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + seqNum_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string seqNum = 6; + */ + public com.google.protobuf.ByteString + getSeqNumBytes() { + Object ref = seqNum_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + seqNum_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string seqNum = 6; + */ + public Builder setSeqNum( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + seqNum_ = value; + onChanged(); + return this; + } + /** + * string seqNum = 6; + */ + public Builder clearSeqNum() { + + seqNum_ = getDefaultInstance().getSeqNum(); + onChanged(); + return this; + } + /** + * string seqNum = 6; + */ + public Builder setSeqNumBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + seqNum_ = value; + onChanged(); + return this; + } + + private Object tag_ = ""; + /** + * string tag = 7; + */ + public String getTag() { + Object ref = tag_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + tag_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string tag = 7; + */ + public com.google.protobuf.ByteString + getTagBytes() { + Object ref = tag_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + tag_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string tag = 7; + */ + public Builder setTag( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + tag_ = value; + onChanged(); + return this; + } + /** + * string tag = 7; + */ + public Builder clearTag() { + + tag_ = getDefaultInstance().getTag(); + onChanged(); + return this; + } + /** + * string tag = 7; + */ + public Builder setTagBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + tag_ = value; + onChanged(); + return this; + } + + private com.google.protobuf.MapField< + String, String> properties_; + private com.google.protobuf.MapField + internalGetProperties() { + if (properties_ == null) { + return com.google.protobuf.MapField.emptyMapField( + PropertiesDefaultEntryHolder.defaultEntry); + } + return properties_; + } + private com.google.protobuf.MapField + internalGetMutableProperties() { + onChanged();; + if (properties_ == null) { + properties_ = com.google.protobuf.MapField.newMapField( + PropertiesDefaultEntryHolder.defaultEntry); + } + if (!properties_.isMutable()) { + properties_ = properties_.copy(); + } + return properties_; + } + + public int getPropertiesCount() { + return internalGetProperties().getMap().size(); + } + /** + * map<string, string> properties = 8; + */ + + public boolean containsProperties( + String key) { + if (key == null) { throw new NullPointerException(); } + return internalGetProperties().getMap().containsKey(key); + } + /** + * Use {@link #getPropertiesMap()} instead. + */ + @Deprecated + public java.util.Map getProperties() { + return getPropertiesMap(); + } + /** + * map<string, string> properties = 8; + */ + + public java.util.Map getPropertiesMap() { + return internalGetProperties().getMap(); + } + /** + * map<string, string> properties = 8; + */ + + public String getPropertiesOrDefault( + String key, + String defaultValue) { + if (key == null) { throw new NullPointerException(); } + java.util.Map map = + internalGetProperties().getMap(); + String value = map.get(key); + if(value == null) return defaultValue; + return value; + } + /** + * map<string, string> properties = 8; + */ + + public String getPropertiesOrThrow( + String key) { + if (key == null) { throw new NullPointerException(); } + java.util.Map map = + internalGetProperties().getMap(); + if (!map.containsKey(key)) { + throw new IllegalArgumentException(); + } + return map.get(key); + } + + public Builder clearProperties() { + internalGetMutableProperties().getMutableMap() + .clear(); + return this; + } + /** + * map<string, string> properties = 8; + */ + + public Builder removeProperties( + String key) { + if (key == null) { throw new NullPointerException(); } + internalGetMutableProperties().getMutableMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @Deprecated + public java.util.Map + getMutableProperties() { + return internalGetMutableProperties().getMutableMap(); + } + /** + * map<string, string> properties = 8; + */ + public Builder putProperties( + String key, + String value) { + if (key == null) { throw new NullPointerException(); } + if (value == null) { throw new NullPointerException(); } + internalGetMutableProperties().getMutableMap() + .put(key, value); + return this; + } + /** + * map<string, string> properties = 8; + */ + + public Builder putAllProperties( + java.util.Map values) { + internalGetMutableProperties().getMutableMap() + .putAll(values); + return this; + } + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFieldsProto3(unknownFields); + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.common.protocol.grpc.Subscription.Reply) + } + + // @@protoc_insertion_point(class_scope:eventmesh.common.protocol.grpc.Subscription.Reply) + private static final Reply DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new Reply(); + } + + public static Reply getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public Reply parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Reply(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public Reply getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private int bitField0_; + public static final int HEADER_FIELD_NUMBER = 1; + private RequestHeader header_; + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public boolean hasHeader() { + return header_ != null; + } + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeader getHeader() { + return header_ == null ? RequestHeader.getDefaultInstance() : header_; + } + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeaderOrBuilder getHeaderOrBuilder() { + return getHeader(); + } + + public static final int CONSUMERGROUP_FIELD_NUMBER = 2; + private volatile Object consumerGroup_; + /** + * string consumerGroup = 2; + */ + public String getConsumerGroup() { + Object ref = consumerGroup_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + consumerGroup_ = s; + return s; + } + } + /** + * string consumerGroup = 2; + */ + public com.google.protobuf.ByteString + getConsumerGroupBytes() { + Object ref = consumerGroup_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + consumerGroup_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SUBSCRIPTIONITEMS_FIELD_NUMBER = 3; + private java.util.List subscriptionItems_; + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public java.util.List getSubscriptionItemsList() { + return subscriptionItems_; + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public java.util.List + getSubscriptionItemsOrBuilderList() { + return subscriptionItems_; + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public int getSubscriptionItemsCount() { + return subscriptionItems_.size(); + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public SubscriptionItem getSubscriptionItems(int index) { + return subscriptionItems_.get(index); + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public SubscriptionItemOrBuilder getSubscriptionItemsOrBuilder( + int index) { + return subscriptionItems_.get(index); + } + + public static final int URL_FIELD_NUMBER = 4; + private volatile Object url_; + /** + * string url = 4; + */ + public String getUrl() { + Object ref = url_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + url_ = s; + return s; + } + } + /** + * string url = 4; + */ + public com.google.protobuf.ByteString + getUrlBytes() { + Object ref = url_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + url_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int REPLY_FIELD_NUMBER = 5; + private Reply reply_; + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + public boolean hasReply() { + return reply_ != null; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + public Reply getReply() { + return reply_ == null ? Reply.getDefaultInstance() : reply_; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + public ReplyOrBuilder getReplyOrBuilder() { + return getReply(); + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (header_ != null) { + output.writeMessage(1, getHeader()); + } + if (!getConsumerGroupBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, consumerGroup_); + } + for (Subscription.SubscriptionItem item : subscriptionItems_) { + output.writeMessage(3, item); + } + if (!getUrlBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 4, url_); + } + if (reply_ != null) { + output.writeMessage(5, getReply()); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (header_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, getHeader()); + } + if (!getConsumerGroupBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, consumerGroup_); + } + for (Subscription.SubscriptionItem item : subscriptionItems_) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, item); + } + if (!getUrlBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, url_); + } + if (reply_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, getReply()); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Subscription)) { + return super.equals(obj); + } + Subscription other = (Subscription) obj; + + boolean result = true; + result = result && (hasHeader() == other.hasHeader()); + if (hasHeader()) { + result = result && getHeader() + .equals(other.getHeader()); + } + result = result && getConsumerGroup() + .equals(other.getConsumerGroup()); + result = result && getSubscriptionItemsList() + .equals(other.getSubscriptionItemsList()); + result = result && getUrl() + .equals(other.getUrl()); + result = result && (hasReply() == other.hasReply()); + if (hasReply()) { + result = result && getReply() + .equals(other.getReply()); + } + return result && unknownFields.equals(other.unknownFields); + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasHeader()) { + hash = (37 * hash) + HEADER_FIELD_NUMBER; + hash = (53 * hash) + getHeader().hashCode(); + } + hash = (37 * hash) + CONSUMERGROUP_FIELD_NUMBER; + hash = (53 * hash) + getConsumerGroup().hashCode(); + if (getSubscriptionItemsCount() > 0) { + hash = (37 * hash) + SUBSCRIPTIONITEMS_FIELD_NUMBER; + hash = (53 * hash) + getSubscriptionItemsList().hashCode(); + } + hash = (37 * hash) + URL_FIELD_NUMBER; + hash = (53 * hash) + getUrl().hashCode(); + if (hasReply()) { + hash = (37 * hash) + REPLY_FIELD_NUMBER; + hash = (53 * hash) + getReply().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static Subscription parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Subscription parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Subscription parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Subscription parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Subscription parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Subscription parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Subscription parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Subscription parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static Subscription parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static Subscription parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static Subscription parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Subscription parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(Subscription prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + return new Builder(parent); + } + /** + * Protobuf type {@code eventmesh.common.protocol.grpc.Subscription} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.common.protocol.grpc.Subscription) + SubscriptionOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_descriptor; + } + + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Subscription.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.grpc.protos.Subscription.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getSubscriptionItemsFieldBuilder(); + } + } + public Builder clear() { + super.clear(); + if (headerBuilder_ == null) { + header_ = null; + } else { + header_ = null; + headerBuilder_ = null; + } + consumerGroup_ = ""; + + if (subscriptionItemsBuilder_ == null) { + subscriptionItems_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000004); + } else { + subscriptionItemsBuilder_.clear(); + } + url_ = ""; + + if (replyBuilder_ == null) { + reply_ = null; + } else { + reply_ = null; + replyBuilder_ = null; + } + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshGrpc.internal_static_eventmesh_common_protocol_grpc_Subscription_descriptor; + } + + public Subscription getDefaultInstanceForType() { + return Subscription.getDefaultInstance(); + } + + public Subscription build() { + Subscription result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public Subscription buildPartial() { + Subscription result = new Subscription(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (headerBuilder_ == null) { + result.header_ = header_; + } else { + result.header_ = headerBuilder_.build(); + } + result.consumerGroup_ = consumerGroup_; + if (subscriptionItemsBuilder_ == null) { + if (((bitField0_ & 0x00000004) == 0x00000004)) { + subscriptionItems_ = java.util.Collections.unmodifiableList(subscriptionItems_); + bitField0_ = (bitField0_ & ~0x00000004); + } + result.subscriptionItems_ = subscriptionItems_; + } else { + result.subscriptionItems_ = subscriptionItemsBuilder_.build(); + } + result.url_ = url_; + if (replyBuilder_ == null) { + result.reply_ = reply_; + } else { + result.reply_ = replyBuilder_.build(); + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder clone() { + return (Builder) super.clone(); + } + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.setField(field, value); + } + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return (Builder) super.clearField(field); + } + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return (Builder) super.clearOneof(oneof); + } + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return (Builder) super.setRepeatedField(field, index, value); + } + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return (Builder) super.addRepeatedField(field, value); + } + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof Subscription) { + return mergeFrom((Subscription)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(Subscription other) { + if (other == Subscription.getDefaultInstance()) return this; + if (other.hasHeader()) { + mergeHeader(other.getHeader()); + } + if (!other.getConsumerGroup().isEmpty()) { + consumerGroup_ = other.consumerGroup_; + onChanged(); + } + if (subscriptionItemsBuilder_ == null) { + if (!other.subscriptionItems_.isEmpty()) { + if (subscriptionItems_.isEmpty()) { + subscriptionItems_ = other.subscriptionItems_; + bitField0_ = (bitField0_ & ~0x00000004); + } else { + ensureSubscriptionItemsIsMutable(); + subscriptionItems_.addAll(other.subscriptionItems_); + } + onChanged(); + } + } else { + if (!other.subscriptionItems_.isEmpty()) { + if (subscriptionItemsBuilder_.isEmpty()) { + subscriptionItemsBuilder_.dispose(); + subscriptionItemsBuilder_ = null; + subscriptionItems_ = other.subscriptionItems_; + bitField0_ = (bitField0_ & ~0x00000004); + subscriptionItemsBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getSubscriptionItemsFieldBuilder() : null; + } else { + subscriptionItemsBuilder_.addAllMessages(other.subscriptionItems_); + } + } + } + if (!other.getUrl().isEmpty()) { + url_ = other.url_; + onChanged(); + } + if (other.hasReply()) { + mergeReply(other.getReply()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Subscription parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (Subscription) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private RequestHeader header_ = null; + private com.google.protobuf.SingleFieldBuilderV3< + RequestHeader, RequestHeader.Builder, RequestHeaderOrBuilder> headerBuilder_; + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public boolean hasHeader() { + return headerBuilder_ != null || header_ != null; + } + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeader getHeader() { + if (headerBuilder_ == null) { + return header_ == null ? RequestHeader.getDefaultInstance() : header_; + } else { + return headerBuilder_.getMessage(); + } + } + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder setHeader(RequestHeader value) { + if (headerBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + header_ = value; + onChanged(); + } else { + headerBuilder_.setMessage(value); + } + + return this; + } + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder setHeader( + RequestHeader.Builder builderForValue) { + if (headerBuilder_ == null) { + header_ = builderForValue.build(); + onChanged(); + } else { + headerBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder mergeHeader(RequestHeader value) { + if (headerBuilder_ == null) { + if (header_ != null) { + header_ = + RequestHeader.newBuilder(header_).mergeFrom(value).buildPartial(); + } else { + header_ = value; + } + onChanged(); + } else { + headerBuilder_.mergeFrom(value); + } + + return this; + } + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public Builder clearHeader() { + if (headerBuilder_ == null) { + header_ = null; + onChanged(); + } else { + header_ = null; + headerBuilder_ = null; + } + + return this; + } + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeader.Builder getHeaderBuilder() { + + onChanged(); + return getHeaderFieldBuilder().getBuilder(); + } + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + public RequestHeaderOrBuilder getHeaderOrBuilder() { + if (headerBuilder_ != null) { + return headerBuilder_.getMessageOrBuilder(); + } else { + return header_ == null ? + RequestHeader.getDefaultInstance() : header_; + } + } + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + private com.google.protobuf.SingleFieldBuilderV3< + RequestHeader, RequestHeader.Builder, RequestHeaderOrBuilder> + getHeaderFieldBuilder() { + if (headerBuilder_ == null) { + headerBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + RequestHeader, RequestHeader.Builder, RequestHeaderOrBuilder>( + getHeader(), + getParentForChildren(), + isClean()); + header_ = null; + } + return headerBuilder_; + } + + private Object consumerGroup_ = ""; + /** + * string consumerGroup = 2; + */ + public String getConsumerGroup() { + Object ref = consumerGroup_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + consumerGroup_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string consumerGroup = 2; + */ + public com.google.protobuf.ByteString + getConsumerGroupBytes() { + Object ref = consumerGroup_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + consumerGroup_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string consumerGroup = 2; + */ + public Builder setConsumerGroup( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + consumerGroup_ = value; + onChanged(); + return this; + } + /** + * string consumerGroup = 2; + */ + public Builder clearConsumerGroup() { + + consumerGroup_ = getDefaultInstance().getConsumerGroup(); + onChanged(); + return this; + } + /** + * string consumerGroup = 2; + */ + public Builder setConsumerGroupBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + consumerGroup_ = value; + onChanged(); + return this; + } + + private java.util.List subscriptionItems_ = + java.util.Collections.emptyList(); + private void ensureSubscriptionItemsIsMutable() { + if (!((bitField0_ & 0x00000004) == 0x00000004)) { + subscriptionItems_ = new java.util.ArrayList(subscriptionItems_); + bitField0_ |= 0x00000004; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + SubscriptionItem, SubscriptionItem.Builder, SubscriptionItemOrBuilder> subscriptionItemsBuilder_; + + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public java.util.List getSubscriptionItemsList() { + if (subscriptionItemsBuilder_ == null) { + return java.util.Collections.unmodifiableList(subscriptionItems_); + } else { + return subscriptionItemsBuilder_.getMessageList(); + } + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public int getSubscriptionItemsCount() { + if (subscriptionItemsBuilder_ == null) { + return subscriptionItems_.size(); + } else { + return subscriptionItemsBuilder_.getCount(); + } + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public SubscriptionItem getSubscriptionItems(int index) { + if (subscriptionItemsBuilder_ == null) { + return subscriptionItems_.get(index); + } else { + return subscriptionItemsBuilder_.getMessage(index); + } + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public Builder setSubscriptionItems( + int index, SubscriptionItem value) { + if (subscriptionItemsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSubscriptionItemsIsMutable(); + subscriptionItems_.set(index, value); + onChanged(); + } else { + subscriptionItemsBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public Builder setSubscriptionItems( + int index, SubscriptionItem.Builder builderForValue) { + if (subscriptionItemsBuilder_ == null) { + ensureSubscriptionItemsIsMutable(); + subscriptionItems_.set(index, builderForValue.build()); + onChanged(); + } else { + subscriptionItemsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public Builder addSubscriptionItems(SubscriptionItem value) { + if (subscriptionItemsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSubscriptionItemsIsMutable(); + subscriptionItems_.add(value); + onChanged(); + } else { + subscriptionItemsBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public Builder addSubscriptionItems( + int index, SubscriptionItem value) { + if (subscriptionItemsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureSubscriptionItemsIsMutable(); + subscriptionItems_.add(index, value); + onChanged(); + } else { + subscriptionItemsBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public Builder addSubscriptionItems( + SubscriptionItem.Builder builderForValue) { + if (subscriptionItemsBuilder_ == null) { + ensureSubscriptionItemsIsMutable(); + subscriptionItems_.add(builderForValue.build()); + onChanged(); + } else { + subscriptionItemsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public Builder addSubscriptionItems( + int index, SubscriptionItem.Builder builderForValue) { + if (subscriptionItemsBuilder_ == null) { + ensureSubscriptionItemsIsMutable(); + subscriptionItems_.add(index, builderForValue.build()); + onChanged(); + } else { + subscriptionItemsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public Builder addAllSubscriptionItems( + Iterable values) { + if (subscriptionItemsBuilder_ == null) { + ensureSubscriptionItemsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, subscriptionItems_); + onChanged(); + } else { + subscriptionItemsBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public Builder clearSubscriptionItems() { + if (subscriptionItemsBuilder_ == null) { + subscriptionItems_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + } else { + subscriptionItemsBuilder_.clear(); + } + return this; + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public Builder removeSubscriptionItems(int index) { + if (subscriptionItemsBuilder_ == null) { + ensureSubscriptionItemsIsMutable(); + subscriptionItems_.remove(index); + onChanged(); + } else { + subscriptionItemsBuilder_.remove(index); + } + return this; + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public SubscriptionItem.Builder getSubscriptionItemsBuilder( + int index) { + return getSubscriptionItemsFieldBuilder().getBuilder(index); + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public SubscriptionItemOrBuilder getSubscriptionItemsOrBuilder( + int index) { + if (subscriptionItemsBuilder_ == null) { + return subscriptionItems_.get(index); } else { + return subscriptionItemsBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public java.util.List + getSubscriptionItemsOrBuilderList() { + if (subscriptionItemsBuilder_ != null) { + return subscriptionItemsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(subscriptionItems_); + } + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public SubscriptionItem.Builder addSubscriptionItemsBuilder() { + return getSubscriptionItemsFieldBuilder().addBuilder( + SubscriptionItem.getDefaultInstance()); + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public SubscriptionItem.Builder addSubscriptionItemsBuilder( + int index) { + return getSubscriptionItemsFieldBuilder().addBuilder( + index, SubscriptionItem.getDefaultInstance()); + } + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + public java.util.List + getSubscriptionItemsBuilderList() { + return getSubscriptionItemsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + SubscriptionItem, SubscriptionItem.Builder, SubscriptionItemOrBuilder> + getSubscriptionItemsFieldBuilder() { + if (subscriptionItemsBuilder_ == null) { + subscriptionItemsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + SubscriptionItem, SubscriptionItem.Builder, SubscriptionItemOrBuilder>( + subscriptionItems_, + ((bitField0_ & 0x00000004) == 0x00000004), + getParentForChildren(), + isClean()); + subscriptionItems_ = null; + } + return subscriptionItemsBuilder_; + } + + private Object url_ = ""; + /** + * string url = 4; + */ + public String getUrl() { + Object ref = url_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + url_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string url = 4; + */ + public com.google.protobuf.ByteString + getUrlBytes() { + Object ref = url_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + url_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string url = 4; + */ + public Builder setUrl( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + url_ = value; + onChanged(); + return this; + } + /** + * string url = 4; + */ + public Builder clearUrl() { + + url_ = getDefaultInstance().getUrl(); + onChanged(); + return this; + } + /** + * string url = 4; + */ + public Builder setUrlBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + url_ = value; + onChanged(); + return this; + } + + private Reply reply_ = null; + private com.google.protobuf.SingleFieldBuilderV3< + Reply, Reply.Builder, ReplyOrBuilder> replyBuilder_; + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + public boolean hasReply() { + return replyBuilder_ != null || reply_ != null; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + public Reply getReply() { + if (replyBuilder_ == null) { + return reply_ == null ? Reply.getDefaultInstance() : reply_; + } else { + return replyBuilder_.getMessage(); + } + } + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + public Builder setReply(Reply value) { + if (replyBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + reply_ = value; + onChanged(); + } else { + replyBuilder_.setMessage(value); + } + + return this; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + public Builder setReply( + Reply.Builder builderForValue) { + if (replyBuilder_ == null) { + reply_ = builderForValue.build(); + onChanged(); + } else { + replyBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + public Builder mergeReply(Reply value) { + if (replyBuilder_ == null) { + if (reply_ != null) { + reply_ = + Reply.newBuilder(reply_).mergeFrom(value).buildPartial(); + } else { + reply_ = value; + } + onChanged(); + } else { + replyBuilder_.mergeFrom(value); + } + + return this; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + public Builder clearReply() { + if (replyBuilder_ == null) { + reply_ = null; + onChanged(); + } else { + reply_ = null; + replyBuilder_ = null; + } + + return this; + } + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + public Reply.Builder getReplyBuilder() { + + onChanged(); + return getReplyFieldBuilder().getBuilder(); + } + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + public ReplyOrBuilder getReplyOrBuilder() { + if (replyBuilder_ != null) { + return replyBuilder_.getMessageOrBuilder(); + } else { + return reply_ == null ? + Reply.getDefaultInstance() : reply_; + } + } + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Reply, Reply.Builder, ReplyOrBuilder> + getReplyFieldBuilder() { + if (replyBuilder_ == null) { + replyBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Reply, Reply.Builder, ReplyOrBuilder>( + getReply(), + getParentForChildren(), + isClean()); + reply_ = null; + } + return replyBuilder_; + } + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFieldsProto3(unknownFields); + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.common.protocol.grpc.Subscription) + } + + // @@protoc_insertion_point(class_scope:eventmesh.common.protocol.grpc.Subscription) + private static final Subscription DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new Subscription(); + } + + public static Subscription getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public Subscription parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Subscription(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public Subscription getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/SubscriptionOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/SubscriptionOrBuilder.java new file mode 100644 index 0000000000..4adff7d4fc --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/grpc/protos/SubscriptionOrBuilder.java @@ -0,0 +1,97 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: eventmesh-client.proto + +package org.apache.eventmesh.common.protocol.grpc.protos; + +@SuppressWarnings({"all"}) +public interface SubscriptionOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.common.protocol.grpc.Subscription) + com.google.protobuf.MessageOrBuilder { + + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + boolean hasHeader(); + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + RequestHeader getHeader(); + /** + * .eventmesh.common.protocol.grpc.RequestHeader header = 1; + */ + RequestHeaderOrBuilder getHeaderOrBuilder(); + + /** + * string consumerGroup = 2; + */ + String getConsumerGroup(); + /** + * string consumerGroup = 2; + */ + com.google.protobuf.ByteString + getConsumerGroupBytes(); + + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + java.util.List + getSubscriptionItemsList(); + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + Subscription.SubscriptionItem getSubscriptionItems(int index); + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + int getSubscriptionItemsCount(); + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + java.util.List + getSubscriptionItemsOrBuilderList(); + /** + * repeated .eventmesh.common.protocol.grpc.Subscription.SubscriptionItem subscriptionItems = 3; + */ + Subscription.SubscriptionItemOrBuilder getSubscriptionItemsOrBuilder( + int index); + + /** + * string url = 4; + */ + String getUrl(); + /** + * string url = 4; + */ + com.google.protobuf.ByteString + getUrlBytes(); + + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + boolean hasReply(); + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + Subscription.Reply getReply(); + /** + * .eventmesh.common.protocol.grpc.Subscription.Reply reply = 5; + */ + Subscription.ReplyOrBuilder getReplyOrBuilder(); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/HttpCommand.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/HttpCommand.java new file mode 100644 index 0000000000..36575e6c20 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/HttpCommand.java @@ -0,0 +1,183 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.ProtocolTransportObject; +import org.apache.eventmesh.common.protocol.http.body.BaseResponseBody; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.protocol.http.common.EventMeshRetCode; +import org.apache.eventmesh.common.protocol.http.header.BaseResponseHeader; +import org.apache.eventmesh.common.protocol.http.header.Header; +import org.apache.eventmesh.common.utils.JsonUtils; + +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; + +import io.netty.buffer.Unpooled; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpHeaderValues; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; + +import lombok.Data; + +@Data +public class HttpCommand implements ProtocolTransportObject { + + public static final long serialVersionUID = 4825360350457735498L; + + private static final AtomicLong requestId = new AtomicLong(0); + + private long opaque; + + private String requestCode; + + public String httpMethod; + + public String httpVersion; + + public Header header; + + public Body body; + + //Command request time + public long reqTime; + + //Command response time + public long resTime; + + public CmdType cmdType = CmdType.REQ; + + public HttpCommand() { + this(null, null, null); + } + + public HttpCommand(String httpMethod, String httpVersion, String requestCode) { + this.httpMethod = httpMethod; + this.httpVersion = httpVersion; + this.reqTime = System.currentTimeMillis(); + this.requestCode = requestCode; + this.opaque = requestId.incrementAndGet(); + } + + public HttpCommand createHttpCommandResponse(Header header, Body body) { + if (StringUtils.isBlank(requestCode)) { + return null; + } + HttpCommand response = new HttpCommand(this.httpMethod, this.httpVersion, this.requestCode); + response.setOpaque(this.opaque); + response.setReqTime(this.reqTime); + response.setHeader(header); + response.setBody(body); + response.setCmdType(CmdType.RES); + response.setResTime(System.currentTimeMillis()); + return response; + } + + public HttpCommand createHttpCommandResponse(EventMeshRetCode eventMeshRetCode) { + if (StringUtils.isBlank(requestCode)) { + return null; + } + HttpCommand response = new HttpCommand(this.httpMethod, this.httpVersion, this.requestCode); + response.setOpaque(this.opaque); + response.setReqTime(this.reqTime); + BaseResponseHeader baseResponseHeader = new BaseResponseHeader(); + baseResponseHeader.setCode(requestCode); + response.setHeader(baseResponseHeader); + BaseResponseBody baseResponseBody = new BaseResponseBody(); + baseResponseBody.setRetCode(eventMeshRetCode.getRetCode()); + baseResponseBody.setRetMsg(eventMeshRetCode.getErrMsg()); + response.setBody(baseResponseBody); + response.setCmdType(CmdType.RES); + response.setResTime(System.currentTimeMillis()); + return response; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("httpCommand={") + .append(cmdType).append(",") + .append(httpMethod).append("/").append(httpVersion).append(",") + .append("requestCode=").append(requestCode).append(",") + .append("opaque=").append(opaque).append(","); + + if (cmdType == CmdType.RES) { + sb.append("cost=").append(resTime - reqTime).append(","); + } + + sb.append("header=").append(header).append(",") + .append("body=").append(body) + .append("}"); + + return sb.toString(); + } + + public String abstractDesc() { + StringBuilder sb = new StringBuilder(); + sb.append("httpCommand={") + .append(cmdType).append(",") + .append(httpMethod).append("/").append(httpVersion).append(",") + .append("requestCode=").append(requestCode).append(",") + .append("opaque=").append(opaque).append(","); + + if (cmdType == CmdType.RES) { + sb.append("cost=").append(resTime - reqTime).append(","); + } + + sb.append("header=").append(header).append(",") + .append("bodySize=").append(body.toString().length()).append("}"); + + return sb.toString(); + } + + public String simpleDesc() { + StringBuilder sb = new StringBuilder(); + sb.append("httpCommand={") + .append(cmdType).append(",") + .append(httpMethod).append("/").append(httpVersion).append(",") + .append("requestCode=").append(requestCode).append("}"); + + return sb.toString(); + } + + public DefaultFullHttpResponse httpResponse() throws Exception { + if (cmdType == CmdType.REQ) { + return null; + } + DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, + Unpooled.wrappedBuffer(Objects.requireNonNull(JsonUtils.serialize(this.getBody())).getBytes(Constants.DEFAULT_CHARSET))); + HttpHeaders headers = response.headers(); + headers.add(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=" + Constants.DEFAULT_CHARSET); + headers.add(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes()); + headers.add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); + Optional.of(this.getHeader().toMap()).ifPresent(customerHeader -> customerHeader.forEach(headers::add)); + return response; + } + + public enum CmdType { + REQ, + RES + } +} \ No newline at end of file diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/HttpEventWrapper.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/HttpEventWrapper.java new file mode 100644 index 0000000000..2bfeaf5630 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/HttpEventWrapper.java @@ -0,0 +1,228 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.ProtocolTransportObject; +import org.apache.eventmesh.common.protocol.http.common.EventMeshRetCode; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.RequestURI; +import org.apache.eventmesh.common.utils.IPUtils; +import org.apache.eventmesh.common.utils.JsonUtils; +import org.apache.eventmesh.common.utils.ThreadUtils; + +import org.apache.commons.lang3.StringUtils; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +import io.netty.buffer.Unpooled; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpHeaderValues; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; + + +public class HttpEventWrapper implements ProtocolTransportObject { + + public static final long serialVersionUID = 7717419089390044263L; + + private Map headerMap = new HashMap<>(); + + private Map sysHeaderMap = new HashMap<>(); + + private byte[] body; + + private String requestURI; + + public String httpMethod; + + public String httpVersion; + + //Command request time + public long reqTime; + + //Command response time + public long resTime; + + public HttpEventWrapper() { + this(null, null, null); + } + + public HttpEventWrapper(String httpMethod, String httpVersion, String requestURI) { + this.httpMethod = httpMethod; + this.httpVersion = httpVersion; + this.reqTime = System.currentTimeMillis(); + this.requestURI = requestURI; + } + + public HttpEventWrapper createHttpResponse(Map responseHeaderMap, Map responseBodyMap) { + if (StringUtils.isBlank(requestURI)) { + return null; + } + HttpEventWrapper response = new HttpEventWrapper(this.httpMethod, this.httpVersion, this.requestURI); + response.setReqTime(this.reqTime); + response.setHeaderMap(responseHeaderMap); + response.setBody(JsonUtils.serialize(responseBodyMap).getBytes(StandardCharsets.UTF_8)); + response.setResTime(System.currentTimeMillis()); + return response; + } + + public HttpEventWrapper createHttpResponse(EventMeshRetCode eventMeshRetCode) { + if (StringUtils.isBlank(requestURI)) { + return null; + } + HttpEventWrapper response = new HttpEventWrapper(this.httpMethod, this.httpVersion, this.requestURI); + response.setReqTime(this.reqTime); + Map responseHeaderMap = new HashMap<>(); + responseHeaderMap.put("requestURI", response.requestURI); + response.setHeaderMap(responseHeaderMap); + Map responseBodyMap = new HashMap<>(); + responseBodyMap.put("retCode", eventMeshRetCode.getRetCode()); + responseBodyMap.put("retMessage", eventMeshRetCode.getErrMsg()); + response.setBody(JsonUtils.serialize(responseBodyMap).getBytes(StandardCharsets.UTF_8)); + response.setResTime(System.currentTimeMillis()); + return response; + } + + public long getReqTime() { + return reqTime; + } + + public void setReqTime(long reqTime) { + this.reqTime = reqTime; + } + + public long getResTime() { + return resTime; + } + + public void setResTime(long resTime) { + this.resTime = resTime; + } + + public String getHttpMethod() { + return httpMethod; + } + + public void setHttpMethod(String httpMethod) { + this.httpMethod = httpMethod; + } + + public String getHttpVersion() { + return httpVersion; + } + + public void setHttpVersion(String httpVersion) { + this.httpVersion = httpVersion; + } + + public String getRequestURI() { + return requestURI; + } + + public void setRequestURI(String requestURI) { + this.requestURI = requestURI; + } + + public Map getHeaderMap() { + return headerMap; + } + + public void setHeaderMap(Map headerMap) { + this.headerMap = headerMap; + } + + public Map getSysHeaderMap() { + return sysHeaderMap; + } + + public void setSysHeaderMap(Map sysHeaderMap) { + this.sysHeaderMap = sysHeaderMap; + } + + public byte[] getBody() { + int len = body.length; + byte[] b = new byte[len]; + System.arraycopy(body, 0, b, 0, len); + return b; + } + + public void setBody(byte[] newBody) { + if (newBody == null || newBody.length == 0) { + return; + } + + int len = newBody.length; + this.body = new byte[len]; + System.arraycopy(newBody, 0, this.body, 0, len); + } + + public DefaultFullHttpResponse httpResponse() throws Exception { + DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, + Unpooled.wrappedBuffer(this.body)); + HttpHeaders headers = response.headers(); + headers.add(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=" + Constants.DEFAULT_CHARSET); + headers.add(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes()); + headers.add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); + Optional.of(this.headerMap).ifPresent(customerHeader -> customerHeader.forEach(headers::add)); + return response; + } + + public void buildSysHeaderForClient() { + // sys attributes + sysHeaderMap.put(ProtocolKey.ClientInstanceKey.ENV, headerMap.getOrDefault(ProtocolKey.ClientInstanceKey.ENV, "env")); + sysHeaderMap.put(ProtocolKey.ClientInstanceKey.IDC, headerMap.getOrDefault(ProtocolKey.ClientInstanceKey.IDC, "idc")); + sysHeaderMap.put(ProtocolKey.ClientInstanceKey.IP, headerMap.getOrDefault(ProtocolKey.ClientInstanceKey.IP, IPUtils.getLocalAddress())); + sysHeaderMap.put(ProtocolKey.ClientInstanceKey.PID, headerMap.getOrDefault(ProtocolKey.ClientInstanceKey.PID, ThreadUtils.getPID())); + sysHeaderMap.put(ProtocolKey.ClientInstanceKey.SYS, headerMap.getOrDefault(ProtocolKey.ClientInstanceKey.SYS, "1234")); + sysHeaderMap.put(ProtocolKey.ClientInstanceKey.USERNAME, headerMap.getOrDefault(ProtocolKey.ClientInstanceKey.USERNAME, "eventmesh")); + sysHeaderMap.put(ProtocolKey.ClientInstanceKey.PASSWD, headerMap.getOrDefault(ProtocolKey.ClientInstanceKey.PASSWD, "pass")); + sysHeaderMap.put(ProtocolKey.ClientInstanceKey.PRODUCERGROUP, + headerMap.getOrDefault(ProtocolKey.ClientInstanceKey.PRODUCERGROUP, "em-http-producer")); + sysHeaderMap.put(ProtocolKey.ClientInstanceKey.CONSUMERGROUP, + headerMap.getOrDefault(ProtocolKey.ClientInstanceKey.CONSUMERGROUP, "em-http-consumer")); + sysHeaderMap.put(ProtocolKey.PROTOCOL_TYPE, "http"); + sysHeaderMap.put(ProtocolKey.PROTOCOL_DESC, "http"); + } + + public void buildSysHeaderForCE() { + // for cloudevents + sysHeaderMap.put(ProtocolKey.CloudEventsKey.ID, UUID.randomUUID().toString()); + sysHeaderMap.put(ProtocolKey.CloudEventsKey.SOURCE, headerMap.getOrDefault("source", URI.create("/"))); + sysHeaderMap.put(ProtocolKey.CloudEventsKey.TYPE, headerMap.getOrDefault("type", "http_request")); + + String topic = headerMap.getOrDefault("subject", "").toString(); + + if (requestURI.startsWith(RequestURI.PUBLISH.getRequestURI())) { + topic = requestURI.substring(RequestURI.PUBLISH.getRequestURI().length() + 1); + } + + if (StringUtils.isEmpty(topic)) { + topic = "TEST-HTTP-TOPIC"; + } + sysHeaderMap.put(ProtocolKey.CloudEventsKey.SUBJECT, topic); + } + +} \ No newline at end of file diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/WebhookProtocolTransportObject.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/WebhookProtocolTransportObject.java new file mode 100644 index 0000000000..5763e29f23 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/WebhookProtocolTransportObject.java @@ -0,0 +1,43 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http; + +import org.apache.eventmesh.common.protocol.ProtocolTransportObject; + +import lombok.Builder; +import lombok.Data; + + +@Data +@Builder +public class WebhookProtocolTransportObject implements ProtocolTransportObject { + + private static final long serialVersionUID = 7821703624838598761L; + + private String cloudEventId; + + private String eventType; + + private String cloudEventName; + + private String cloudEventSource; + + private String dataContentType; + + private byte[] body; +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/BaseRequestBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/BaseRequestBody.java new file mode 100644 index 0000000000..423872bdf2 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/BaseRequestBody.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body; + +import java.util.HashMap; +import java.util.Map; + +public class BaseRequestBody extends Body { + + public static BaseRequestBody buildBody(Map bodyParam) { + return new BaseRequestBody(); + } + + @Override + public Map toMap() { + return new HashMap(); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/BaseResponseBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/BaseResponseBody.java new file mode 100644 index 0000000000..aefa711840 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/BaseResponseBody.java @@ -0,0 +1,66 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body; + + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import java.util.HashMap; +import java.util.Map; + +public class BaseResponseBody extends Body { + + private Integer retCode; + + private String retMsg; + + private long resTime = System.currentTimeMillis(); + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getRetMsg() { + return retMsg; + } + + public void setRetMsg(String retMsg) { + this.retMsg = retMsg; + } + + public long getResTime() { + return resTime; + } + + public void setResTime(long resTime) { + this.resTime = resTime; + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(ProtocolKey.RETCODE, retCode); + map.put(ProtocolKey.RETMSG, retMsg); + map.put(ProtocolKey.RESTIME, resTime); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/Body.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/Body.java new file mode 100644 index 0000000000..3dc8e6c272 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/Body.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body; + + +import org.apache.eventmesh.common.protocol.http.body.client.HeartbeatRequestBody; +import org.apache.eventmesh.common.protocol.http.body.client.RegRequestBody; +import org.apache.eventmesh.common.protocol.http.body.client.SubscribeRequestBody; +import org.apache.eventmesh.common.protocol.http.body.client.UnRegRequestBody; +import org.apache.eventmesh.common.protocol.http.body.client.UnSubscribeRequestBody; +import org.apache.eventmesh.common.protocol.http.body.message.PushMessageRequestBody; +import org.apache.eventmesh.common.protocol.http.body.message.ReplyMessageRequestBody; +import org.apache.eventmesh.common.protocol.http.body.message.SendMessageBatchRequestBody; +import org.apache.eventmesh.common.protocol.http.body.message.SendMessageBatchV2RequestBody; +import org.apache.eventmesh.common.protocol.http.body.message.SendMessageRequestBody; +import org.apache.eventmesh.common.protocol.http.common.RequestCode; + +import java.util.Map; + +public abstract class Body { + + public abstract Map toMap(); + + public static Body buildBody(String requestCode, Map originalMap) throws Exception { + if (String.valueOf(RequestCode.MSG_BATCH_SEND.getRequestCode()).equals(requestCode)) { + return SendMessageBatchRequestBody.buildBody(originalMap); + } + if (String.valueOf(RequestCode.MSG_BATCH_SEND_V2.getRequestCode()).equals(requestCode)) { + return SendMessageBatchV2RequestBody.buildBody(originalMap); + } else if (String.valueOf(RequestCode.MSG_SEND_ASYNC.getRequestCode()).equals(requestCode)) { + return SendMessageRequestBody.buildBody(originalMap); + } else if (String.valueOf(RequestCode.MSG_SEND_SYNC.getRequestCode()).equals(requestCode)) { + return SendMessageRequestBody.buildBody(originalMap); + } else if (String.valueOf(RequestCode.HTTP_PUSH_CLIENT_ASYNC.getRequestCode()).equals(requestCode)) { + return PushMessageRequestBody.buildBody(originalMap); + } else if (String.valueOf(RequestCode.HTTP_PUSH_CLIENT_SYNC.getRequestCode()).equals(requestCode)) { + return PushMessageRequestBody.buildBody(originalMap); + } else if (String.valueOf(RequestCode.REGISTER.getRequestCode()).equals(requestCode)) { + return RegRequestBody.buildBody(originalMap); + } else if (String.valueOf(RequestCode.UNREGISTER.getRequestCode()).equals(requestCode)) { + return UnRegRequestBody.buildBody(originalMap); + } else if (String.valueOf(RequestCode.SUBSCRIBE.getRequestCode()).equals(requestCode)) { + return SubscribeRequestBody.buildBody(originalMap); + } else if (String.valueOf(RequestCode.UNSUBSCRIBE.getRequestCode()).equals(requestCode)) { + return UnSubscribeRequestBody.buildBody(originalMap); + } else if (String.valueOf(RequestCode.HEARTBEAT.getRequestCode()).equals(requestCode)) { + return HeartbeatRequestBody.buildBody(originalMap); + } else if (String.valueOf(RequestCode.REPLY_MESSAGE.getRequestCode()).equals(requestCode)) { + return ReplyMessageRequestBody.buildBody(originalMap); + } else if (String.valueOf(RequestCode.ADMIN_SHUTDOWN.getRequestCode()).equals(requestCode)) { + return BaseRequestBody.buildBody(originalMap); + } else { + throw new Exception(); + } + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/HeartbeatRequestBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/HeartbeatRequestBody.java new file mode 100644 index 0000000000..b65f7c39d4 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/HeartbeatRequestBody.java @@ -0,0 +1,77 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.client; + +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.utils.JsonUtils; + +import org.apache.commons.collections4.MapUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.type.TypeReference; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@EqualsAndHashCode(callSuper = true) +@Data +@ToString +public class HeartbeatRequestBody extends Body { + + public static final String CLIENTTYPE = "clientType"; + public static final String HEARTBEATENTITIES = "heartbeatEntities"; + public static final String CONSUMERGROUP = "consumerGroup"; + + private String consumerGroup; + + private String clientType; + + private List heartbeatEntities; + + public static HeartbeatRequestBody buildBody(Map bodyParam) { + HeartbeatRequestBody body = new HeartbeatRequestBody(); + body.setClientType(MapUtils.getString(bodyParam, CLIENTTYPE)); + body.setConsumerGroup(MapUtils.getString(bodyParam, CONSUMERGROUP)); + body.setHeartbeatEntities(JsonUtils + .deserialize(MapUtils.getString(bodyParam, HEARTBEATENTITIES), + new TypeReference>() { + })); + return body; + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(CLIENTTYPE, clientType); + map.put(CONSUMERGROUP, consumerGroup); + map.put(HEARTBEATENTITIES, JsonUtils.serialize(heartbeatEntities)); + return map; + } + + @ToString + public static class HeartbeatEntity { + public String topic; + public String serviceId; + public String url; + public String instanceId; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/HeartbeatResponseBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/HeartbeatResponseBody.java new file mode 100644 index 0000000000..fca6d2f6ed --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/HeartbeatResponseBody.java @@ -0,0 +1,91 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.client; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.apache.commons.lang3.time.DateFormatUtils; + +import java.util.HashMap; +import java.util.Map; + +public class HeartbeatResponseBody extends Body { + + //return code + private Integer retCode; + + //response message + private String retMsg; + + //response time + private long resTime = System.currentTimeMillis(); + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getRetMsg() { + return retMsg; + } + + public void setRetMsg(String retMsg) { + this.retMsg = retMsg; + } + + public long getResTime() { + return resTime; + } + + public void setResTime(long resTime) { + this.resTime = resTime; + } + + public static HeartbeatResponseBody buildBody(Integer retCode, String retMsg) { + HeartbeatResponseBody heartbeatResponseBody = new HeartbeatResponseBody(); + heartbeatResponseBody.setRetMsg(retMsg); + heartbeatResponseBody.setResTime(System.currentTimeMillis()); + heartbeatResponseBody.setRetCode(retCode); + return heartbeatResponseBody; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("heartbeatResponseBody={") + .append("retCode=").append(retCode).append(",") + .append("retMsg=").append(retMsg).append(",") + .append("resTime=").append(DateFormatUtils.format(resTime, Constants.DATE_FORMAT)).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(ProtocolKey.RETCODE, retCode); + map.put(ProtocolKey.RETMSG, retMsg); + map.put(ProtocolKey.RESTIME, resTime); + return map; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/RegRequestBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/RegRequestBody.java new file mode 100644 index 0000000000..affffdce09 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/RegRequestBody.java @@ -0,0 +1,97 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.client; + +import org.apache.eventmesh.common.protocol.SubscriptionItem; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.utils.JsonUtils; + +import org.apache.commons.collections4.MapUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.type.TypeReference; + +public class RegRequestBody extends Body { + + public static final String CLIENTTYPE = "clientType"; + + public static final String TOPICS = "topics"; + + public static final String ENDPOINT = "endpoint"; + + private String clientType; + + private String endPoint; + + private List topics; + + public List getTopics() { + return topics; + } + + public void setTopics(List topics) { + this.topics = topics; + } + + public String getClientType() { + return clientType; + } + + public void setClientType(String clientType) { + this.clientType = clientType; + } + + public String getEndPoint() { + return endPoint; + } + + public void setEndPoint(String endPoint) { + this.endPoint = endPoint; + } + + public static RegRequestBody buildBody(Map bodyParam) { + RegRequestBody body = new RegRequestBody(); + body.setClientType(MapUtils.getString(bodyParam, CLIENTTYPE)); + body.setEndPoint(MapUtils.getString(bodyParam, ENDPOINT)); + body.setTopics(JsonUtils.deserialize(MapUtils.getString(bodyParam, TOPICS), + new TypeReference>() { + })); + return body; + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(CLIENTTYPE, clientType); + map.put(ENDPOINT, endPoint); + map.put(TOPICS, JsonUtils.serialize(topics)); + return map; + } + + @Override + public String toString() { + return "regRequestBody{" + + "clientType='" + clientType + '\'' + + ", endPoint='" + endPoint + '\'' + + ", topics=" + topics + + '}'; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/RegResponseBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/RegResponseBody.java new file mode 100644 index 0000000000..497a7417dc --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/RegResponseBody.java @@ -0,0 +1,85 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.client; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.apache.commons.lang3.time.DateFormatUtils; + +import java.util.HashMap; +import java.util.Map; + +public class RegResponseBody extends Body { + private Integer retCode; + private String retMsg; + private long resTime = System.currentTimeMillis(); + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getRetMsg() { + return retMsg; + } + + public void setRetMsg(String retMsg) { + this.retMsg = retMsg; + } + + public long getResTime() { + return resTime; + } + + public void setResTime(long resTime) { + this.resTime = resTime; + } + + public static RegResponseBody buildBody(Integer retCode, String retMsg) { + RegResponseBody regResponseBody = new RegResponseBody(); + regResponseBody.setRetMsg(retMsg); + regResponseBody.setResTime(System.currentTimeMillis()); + regResponseBody.setRetCode(retCode); + return regResponseBody; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("regResponseBody={") + .append("retCode=").append(retCode).append(",") + .append("retMsg=").append(retMsg).append(",") + .append("resTime=").append(DateFormatUtils.format(resTime, Constants.DATE_FORMAT)).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(ProtocolKey.RETCODE, retCode); + map.put(ProtocolKey.RETMSG, retMsg); + map.put(ProtocolKey.RESTIME, resTime); + return map; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/SubscribeRequestBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/SubscribeRequestBody.java new file mode 100644 index 0000000000..df413c1c33 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/SubscribeRequestBody.java @@ -0,0 +1,97 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.client; + +import org.apache.eventmesh.common.protocol.SubscriptionItem; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.utils.JsonUtils; + +import org.apache.commons.collections4.MapUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.type.TypeReference; + +public class SubscribeRequestBody extends Body { + + public static final String TOPIC = "topic"; + + public static final String URL = "url"; + + public static final String CONSUMERGROUP = "consumerGroup"; + + private List topics; + + private String url; + + private String consumerGroup; + + public String getConsumerGroup() { + return consumerGroup; + } + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } + + public List getTopics() { + return topics; + } + + public void setTopics(List topics) { + this.topics = topics; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public static SubscribeRequestBody buildBody(Map bodyParam) { + SubscribeRequestBody body = new SubscribeRequestBody(); + body.setUrl(MapUtils.getString(bodyParam, URL)); + body.setTopics(JsonUtils.deserialize(MapUtils.getString(bodyParam, TOPIC), + new TypeReference>() { + })); + body.setConsumerGroup(MapUtils.getString(bodyParam, CONSUMERGROUP)); + return body; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(URL, url); + map.put(TOPIC, JsonUtils.serialize(topics)); + map.put(CONSUMERGROUP, consumerGroup); + return map; + } + + @Override + public String toString() { + return "subscribeBody{" + + "consumerGroup='" + consumerGroup + '\'' + + ", url='" + url + '\'' + + ", topics=" + topics + + '}'; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/SubscribeResponseBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/SubscribeResponseBody.java new file mode 100644 index 0000000000..0d856713bd --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/SubscribeResponseBody.java @@ -0,0 +1,84 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.client; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.apache.commons.lang3.time.DateFormatUtils; + +import java.util.HashMap; +import java.util.Map; + +public class SubscribeResponseBody extends Body { + private Integer retCode; + private String retMsg; + private long resTime = System.currentTimeMillis(); + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getRetMsg() { + return retMsg; + } + + public void setRetMsg(String retMsg) { + this.retMsg = retMsg; + } + + public long getResTime() { + return resTime; + } + + public void setResTime(long resTime) { + this.resTime = resTime; + } + + public static SubscribeResponseBody buildBody(Integer retCode, String retMsg) { + SubscribeResponseBody regResponseBody = new SubscribeResponseBody(); + regResponseBody.setRetMsg(retMsg); + regResponseBody.setResTime(System.currentTimeMillis()); + regResponseBody.setRetCode(retCode); + return regResponseBody; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("regResponseBody={") + .append("retCode=").append(retCode).append(",") + .append("retMsg=").append(retMsg).append(",") + .append("resTime=").append(DateFormatUtils.format(resTime, Constants.DATE_FORMAT)).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(ProtocolKey.RETCODE, retCode); + map.put(ProtocolKey.RETMSG, retMsg); + map.put(ProtocolKey.RESTIME, resTime); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/UnRegRequestBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/UnRegRequestBody.java new file mode 100644 index 0000000000..6fa82bda7c --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/UnRegRequestBody.java @@ -0,0 +1,99 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.client; + +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.utils.JsonUtils; + +import org.apache.commons.collections4.MapUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.type.TypeReference; + +public class UnRegRequestBody extends Body { + + public static final String CLIENTTYPE = "clientType"; + + public static final String TOPICS = "topics"; + + private String clientType; + + private List topics; + + public List getTopics() { + return topics; + } + + public void setTopics(List topics) { + this.topics = topics; + } + + public String getClientType() { + return clientType; + } + + public void setClientType(String clientType) { + this.clientType = clientType; + } + + public static UnRegRequestBody buildBody(Map bodyParam) { + UnRegRequestBody body = new UnRegRequestBody(); + body.setClientType(MapUtils.getString(bodyParam, CLIENTTYPE)); + body.setTopics(JsonUtils.deserialize(MapUtils.getString(bodyParam, TOPICS), + new TypeReference>() { + })); + return body; + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(CLIENTTYPE, clientType); + map.put(TOPICS, JsonUtils.serialize(topics)); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("regRequestBody={") + .append("clientType=").append(clientType) + .append("topics=").append(topics) + .append("}"); + return sb.toString(); + } + + public static class UnRegTopicEntity { + public String topic; + public String serviceId; + public String instanceId; + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("unRegTopicEntity={") + .append("topic=").append(topic).append(",") + .append("serviceId=").append(serviceId).append(",") + .append("instanceId=").append(instanceId).append("}"); + return sb.toString(); + } + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/UnRegResponseBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/UnRegResponseBody.java new file mode 100644 index 0000000000..c43502f056 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/UnRegResponseBody.java @@ -0,0 +1,85 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.client; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.apache.commons.lang3.time.DateFormatUtils; + +import java.util.HashMap; +import java.util.Map; + +public class UnRegResponseBody extends Body { + private Integer retCode; + private String retMsg; + private long resTime = System.currentTimeMillis(); + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getRetMsg() { + return retMsg; + } + + public void setRetMsg(String retMsg) { + this.retMsg = retMsg; + } + + public long getResTime() { + return resTime; + } + + public void setResTime(long resTime) { + this.resTime = resTime; + } + + public static UnRegResponseBody buildBody(Integer retCode, String retMsg) { + UnRegResponseBody regResponseBody = new UnRegResponseBody(); + regResponseBody.setRetMsg(retMsg); + regResponseBody.setResTime(System.currentTimeMillis()); + regResponseBody.setRetCode(retCode); + return regResponseBody; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("regResponseBody={") + .append("retCode=").append(retCode).append(",") + .append("retMsg=").append(retMsg).append(",") + .append("resTime=").append(DateFormatUtils.format(resTime, Constants.DATE_FORMAT)).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(ProtocolKey.RETCODE, retCode); + map.put(ProtocolKey.RETMSG, retMsg); + map.put(ProtocolKey.RESTIME, resTime); + return map; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/UnSubscribeRequestBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/UnSubscribeRequestBody.java new file mode 100644 index 0000000000..ca9db6210e --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/UnSubscribeRequestBody.java @@ -0,0 +1,96 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.client; + +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.utils.JsonUtils; + +import org.apache.commons.collections4.MapUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.type.TypeReference; + +public class UnSubscribeRequestBody extends Body { + + public static final String TOPIC = "topic"; + + public static final String URL = "url"; + + public static final String CONSUMERGROUP = "consumerGroup"; + + private List topics; + + private String url; + + private String consumerGroup; + + public List getTopics() { + return topics; + } + + public void setTopics(List topics) { + this.topics = topics; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getConsumerGroup() { + return consumerGroup; + } + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } + + public static UnSubscribeRequestBody buildBody(Map bodyParam) { + UnSubscribeRequestBody body = new UnSubscribeRequestBody(); + body.setUrl(MapUtils.getString(bodyParam, URL)); + body.setTopics(JsonUtils + .deserialize(MapUtils.getString(bodyParam, TOPIC), new TypeReference>() { + })); + body.setConsumerGroup(MapUtils.getString(bodyParam, CONSUMERGROUP)); + return body; + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(URL, url); + map.put(TOPIC, JsonUtils.serialize(topics)); + map.put(CONSUMERGROUP, consumerGroup); + return map; + } + + @Override + public String toString() { + return "unSubscribeRequestBody{" + + "consumerGroup='" + consumerGroup + '\'' + + ", url='" + url + '\'' + + ", topics=" + topics + + '}'; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/UnSubscribeResponseBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/UnSubscribeResponseBody.java new file mode 100644 index 0000000000..621f7dca22 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/client/UnSubscribeResponseBody.java @@ -0,0 +1,85 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.client; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.apache.commons.lang3.time.DateFormatUtils; + +import java.util.HashMap; +import java.util.Map; + +public class UnSubscribeResponseBody extends Body { + + private Integer retCode; + private String retMsg; + private long resTime = System.currentTimeMillis(); + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getRetMsg() { + return retMsg; + } + + public void setRetMsg(String retMsg) { + this.retMsg = retMsg; + } + + public long getResTime() { + return resTime; + } + + public void setResTime(long resTime) { + this.resTime = resTime; + } + + public static UnSubscribeResponseBody buildBody(Integer retCode, String retMsg) { + UnSubscribeResponseBody regResponseBody = new UnSubscribeResponseBody(); + regResponseBody.setRetMsg(retMsg); + regResponseBody.setResTime(System.currentTimeMillis()); + regResponseBody.setRetCode(retCode); + return regResponseBody; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("regResponseBody={") + .append("retCode=").append(retCode).append(",") + .append("retMsg=").append(retMsg).append(",") + .append("resTime=").append(DateFormatUtils.format(resTime, Constants.DATE_FORMAT)).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(ProtocolKey.RETCODE, retCode); + map.put(ProtocolKey.RETMSG, retMsg); + map.put(ProtocolKey.RESTIME, resTime); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/PushMessageRequestBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/PushMessageRequestBody.java new file mode 100644 index 0000000000..183e4cb605 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/PushMessageRequestBody.java @@ -0,0 +1,142 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.message; + +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.utils.JsonUtils; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.core.type.TypeReference; + +public class PushMessageRequestBody extends Body { + + public static final String RANDOMNO = "randomNo"; + public static final String TOPIC = "topic"; + public static final String BIZSEQNO = "bizseqno"; + public static final String UNIQUEID = "uniqueId"; + public static final String CONTENT = "content"; + public static final String EXTFIELDS = "extFields"; + + private String randomNo; + + private String topic; + + private String content; + + private String bizSeqNo; + + private String uniqueId; + + private Map extFields; + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public String getRandomNo() { + return randomNo; + } + + public void setRandomNo(String randomNo) { + this.randomNo = randomNo; + } + + public String getBizSeqNo() { + return bizSeqNo; + } + + public void setBizSeqNo(String bizSeqNo) { + this.bizSeqNo = bizSeqNo; + } + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Map getExtFields() { + return extFields; + } + + public void setExtFields(Map extFields) { + this.extFields = extFields; + } + + public static PushMessageRequestBody buildBody(final Map bodyParam) { + PushMessageRequestBody pushMessageRequestBody = new PushMessageRequestBody(); + pushMessageRequestBody.setContent(MapUtils.getString(bodyParam, CONTENT)); + pushMessageRequestBody.setBizSeqNo(MapUtils.getString(bodyParam, BIZSEQNO)); + pushMessageRequestBody.setTopic(MapUtils.getString(bodyParam, TOPIC)); + pushMessageRequestBody.setUniqueId(MapUtils.getString(bodyParam, UNIQUEID)); + pushMessageRequestBody.setRandomNo(MapUtils.getString(bodyParam, RANDOMNO)); + String extFields = MapUtils.getString(bodyParam, EXTFIELDS); + + if (StringUtils.isNotBlank(extFields)) { + pushMessageRequestBody.setExtFields( + JsonUtils.deserialize(extFields, new TypeReference>() { + })); + } + return pushMessageRequestBody; + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(RANDOMNO, randomNo); + map.put(TOPIC, topic); + map.put(CONTENT, content); + map.put(BIZSEQNO, bizSeqNo); + map.put(UNIQUEID, uniqueId); + map.put(EXTFIELDS, JsonUtils.serialize(extFields)); + + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("pushMessageRequestBody={") + .append("randomNo=").append(randomNo).append(",") + .append("topic=").append(topic).append(",") + .append("bizSeqNo=").append(bizSeqNo).append(",") + .append("uniqueId=").append(uniqueId).append(",") + .append("content=").append(content).append(",") + .append("extFields=").append(extFields).append("}"); + return sb.toString(); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/PushMessageResponseBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/PushMessageResponseBody.java new file mode 100644 index 0000000000..01000b0d0f --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/PushMessageResponseBody.java @@ -0,0 +1,87 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.message; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.apache.commons.lang3.time.DateFormatUtils; + +import java.util.HashMap; +import java.util.Map; + +public class PushMessageResponseBody extends Body { + + private Integer retCode; + + private String retMsg; + + private long resTime = System.currentTimeMillis(); + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getRetMsg() { + return retMsg; + } + + public void setRetMsg(String retMsg) { + this.retMsg = retMsg; + } + + public long getResTime() { + return resTime; + } + + public void setResTime(long resTime) { + this.resTime = resTime; + } + + public static PushMessageResponseBody buildBody(Integer retCode, String retMsg) { + PushMessageResponseBody pushMessageResponseBody = new PushMessageResponseBody(); + pushMessageResponseBody.setResTime(System.currentTimeMillis()); + pushMessageResponseBody.setRetCode(retCode); + pushMessageResponseBody.setRetMsg(retMsg); + return pushMessageResponseBody; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("pushMessageResponseBody={") + .append("retCode=").append(retCode).append(",") + .append("retMsg=").append(retMsg).append(",") + .append("resTime=").append(DateFormatUtils.format(resTime, Constants.DATE_FORMAT)).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(ProtocolKey.RETCODE, retCode); + map.put(ProtocolKey.RETMSG, retMsg); + map.put(ProtocolKey.RESTIME, resTime); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/ReplyMessageRequestBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/ReplyMessageRequestBody.java new file mode 100644 index 0000000000..b45b1cf935 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/ReplyMessageRequestBody.java @@ -0,0 +1,140 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.message; + +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.utils.JsonUtils; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.core.type.TypeReference; + +public class ReplyMessageRequestBody extends Body { + + public static final String ORIGTOPIC = "origtopic"; + public static final String BIZSEQNO = "bizseqno"; + public static final String UNIQUEID = "uniqueid"; + public static final String CONTENT = "content"; + public static final String EXTFIELDS = "extFields"; + public static final String PRODUCERGROUP = "producergroup"; + + private String bizSeqNo; + + private String uniqueId; + + private String content; + + private String origTopic; + + private Map extFields; + + private String producerGroup; + + public String getOrigTopic() { + return origTopic; + } + + public void setOrigTopic(String origTopic) { + this.origTopic = origTopic; + } + + public String getBizSeqNo() { + return bizSeqNo; + } + + public void setBizSeqNo(String bizSeqNo) { + this.bizSeqNo = bizSeqNo; + } + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Map getExtFields() { + return extFields; + } + + public void setExtFields(Map extFields) { + this.extFields = extFields; + } + + public String getProducerGroup() { + return producerGroup; + } + + public void setProducerGroup(String producerGroup) { + this.producerGroup = producerGroup; + } + + public static ReplyMessageRequestBody buildBody(Map bodyParam) { + ReplyMessageRequestBody body = new ReplyMessageRequestBody(); + body.setBizSeqNo(MapUtils.getString(bodyParam, BIZSEQNO)); + body.setUniqueId(MapUtils.getString(bodyParam, UNIQUEID)); + body.setContent(MapUtils.getString(bodyParam, CONTENT)); + body.setOrigTopic(MapUtils.getString(bodyParam, ORIGTOPIC)); + String extFields = MapUtils.getString(bodyParam, EXTFIELDS); + if (StringUtils.isNotBlank(extFields)) { + body.setExtFields( + JsonUtils.deserialize(extFields, new TypeReference>() { + })); + } + body.setProducerGroup(MapUtils.getString(bodyParam, PRODUCERGROUP)); + return body; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("replyMessageRequestBody={") + .append("bizSeqNo=").append(bizSeqNo).append(",") + .append("uniqueId=").append(uniqueId).append(",") + .append("origTopic=").append(origTopic).append(",") + .append("content=").append(content).append(",") + .append("producerGroup=").append(producerGroup).append(",") + .append("extFields=").append(extFields).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(BIZSEQNO, bizSeqNo); + map.put(ORIGTOPIC, origTopic); + map.put(UNIQUEID, uniqueId); + map.put(CONTENT, content); + map.put(EXTFIELDS, JsonUtils.serialize(extFields)); + map.put(PRODUCERGROUP, producerGroup); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/ReplyMessageResponseBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/ReplyMessageResponseBody.java new file mode 100644 index 0000000000..342f151c0a --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/ReplyMessageResponseBody.java @@ -0,0 +1,91 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.message; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.apache.commons.lang3.time.DateFormatUtils; + +import java.util.HashMap; +import java.util.Map; + +public class ReplyMessageResponseBody extends Body { + + //return code + private Integer retCode; + + //response message + private String retMsg; + + //response time + private long resTime = System.currentTimeMillis(); + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getRetMsg() { + return retMsg; + } + + public void setRetMsg(String retMsg) { + this.retMsg = retMsg; + } + + public long getResTime() { + return resTime; + } + + public void setResTime(long resTime) { + this.resTime = resTime; + } + + public static ReplyMessageResponseBody buildBody(Integer retCode, String retMsg) { + ReplyMessageResponseBody replyMessageResponseBody = new ReplyMessageResponseBody(); + replyMessageResponseBody.setRetMsg(retMsg); + replyMessageResponseBody.setResTime(System.currentTimeMillis()); + replyMessageResponseBody.setRetCode(retCode); + return replyMessageResponseBody; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("replyMessageResponseBody={") + .append("retCode=").append(retCode).append(",") + .append("retMsg=").append(retMsg).append(",") + .append("resTime=").append(DateFormatUtils.format(resTime, Constants.DATE_FORMAT)).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(ProtocolKey.RETCODE, retCode); + map.put(ProtocolKey.RETMSG, retMsg); + map.put(ProtocolKey.RESTIME, resTime); + return map; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageBatchRequestBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageBatchRequestBody.java new file mode 100644 index 0000000000..da77955333 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageBatchRequestBody.java @@ -0,0 +1,143 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.message; + +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.utils.JsonUtils; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.type.TypeReference; + +public class SendMessageBatchRequestBody extends Body { + + public static final String BATCHID = "batchId"; + public static final String CONTENTS = "contents"; + public static final String SIZE = "size"; + public static final String PRODUCERGROUP = "producerGroup"; + + private String batchId; + + private List contents; + + private String size; + + private String producerGroup; + + public SendMessageBatchRequestBody() { + } + + public String getBatchId() { + return batchId; + } + + public void setBatchId(String batchId) { + this.batchId = batchId; + } + + public List getContents() { + return contents; + } + + public void setContents(List contents) { + this.contents = contents; + } + + public String getSize() { + return size; + } + + public void setSize(String size) { + this.size = size; + } + + public String getProducerGroup() { + return producerGroup; + } + + public void setProducerGroup(String producerGroup) { + this.producerGroup = producerGroup; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("sendMessageBatchRequestBody={") + .append("batchId=").append(batchId).append(",") + .append("size=").append(size).append(",") + .append("producerGroup=").append(producerGroup).append(",") + .append("contents=").append(JsonUtils.serialize(contents)).append("}"); + return sb.toString(); + } + + public static class BatchMessageEntity { + public String bizSeqNo; + public String topic; + public String msg; + public String tag; + public String ttl; + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("batchMessageEntity={") + .append("bizSeqNo=").append(bizSeqNo).append(",") + .append("topic=").append(topic).append(",") + .append("msg=").append(msg).append(",") + .append("ttl=").append(ttl).append(",") + .append("tag=").append(tag).append("}"); + return sb.toString(); + } + } + + public static SendMessageBatchRequestBody buildBody(final Map bodyParam) { + String batchId = MapUtils.getString(bodyParam, + BATCHID); + String size = StringUtils.isBlank(MapUtils.getString(bodyParam, + SIZE)) ? "1" : MapUtils.getString(bodyParam, + SIZE); + String contents = MapUtils.getString(bodyParam, + CONTENTS, null); + SendMessageBatchRequestBody body = new SendMessageBatchRequestBody(); + body.setBatchId(batchId); + if (StringUtils.isNotBlank(contents)) { + body.setContents( + JsonUtils.deserialize(contents, new TypeReference>() { + })); + } + body.setSize(size); + body.setProducerGroup(MapUtils.getString(bodyParam, PRODUCERGROUP)); + return body; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(BATCHID, batchId); + map.put(SIZE, size); + map.put(CONTENTS, contents); + map.put(PRODUCERGROUP, producerGroup); + return map; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageBatchResponseBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageBatchResponseBody.java new file mode 100644 index 0000000000..f504473673 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageBatchResponseBody.java @@ -0,0 +1,90 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.message; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.apache.commons.lang3.time.DateFormatUtils; + +import java.util.HashMap; +import java.util.Map; + +public class SendMessageBatchResponseBody extends Body { + + //return code + private Integer retCode; + + //response message + private String retMsg; + + //response time + private long resTime = System.currentTimeMillis(); + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getRetMsg() { + return retMsg; + } + + public void setRetMsg(String retMsg) { + this.retMsg = retMsg; + } + + public long getResTime() { + return resTime; + } + + public void setResTime(long resTime) { + this.resTime = resTime; + } + + public static SendMessageBatchResponseBody buildBody(Integer retCode, String retMsg) { + SendMessageBatchResponseBody sendMessageBatchResponseBody = new SendMessageBatchResponseBody(); + sendMessageBatchResponseBody.setRetMsg(retMsg); + sendMessageBatchResponseBody.setRetCode(retCode); + sendMessageBatchResponseBody.setResTime(System.currentTimeMillis()); + return sendMessageBatchResponseBody; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("sendMessageBatchResponseBody={") + .append("retCode=").append(retCode).append(",") + .append("retMsg=").append(retMsg).append(",") + .append("resTime=").append(DateFormatUtils.format(resTime, Constants.DATE_FORMAT)).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(ProtocolKey.RETCODE, retCode); + map.put(ProtocolKey.RETMSG, retMsg); + map.put(ProtocolKey.RESTIME, resTime); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageBatchV2RequestBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageBatchV2RequestBody.java new file mode 100644 index 0000000000..5abd7bc0cf --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageBatchV2RequestBody.java @@ -0,0 +1,141 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.message; + +import org.apache.eventmesh.common.protocol.http.body.Body; + +import org.apache.commons.collections4.MapUtils; + +import java.util.HashMap; +import java.util.Map; + +public class SendMessageBatchV2RequestBody extends Body { + + public static final String BIZSEQNO = "bizseqno"; + public static final String TOPIC = "topic"; + public static final String MSG = "msg"; + public static final String TAG = "tag"; + public static final String TTL = "ttl"; + public static final String PRODUCERGROUP = "producergroup"; + + private String bizSeqNo; + + private String topic; + + private String msg; + + private String tag; + + private String ttl; + + private String producerGroup; + + public String getBizSeqNo() { + return bizSeqNo; + } + + public void setBizSeqNo(String bizSeqNo) { + this.bizSeqNo = bizSeqNo; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public String getTtl() { + return ttl; + } + + public void setTtl(String ttl) { + this.ttl = ttl; + } + + public String getProducerGroup() { + return producerGroup; + } + + public void setProducerGroup(String producerGroup) { + this.producerGroup = producerGroup; + } + + public static SendMessageBatchV2RequestBody buildBody(final Map bodyParam) { + String bizSeqno = MapUtils.getString(bodyParam, + BIZSEQNO); + String topic = MapUtils.getString(bodyParam, + TOPIC); + String tag = MapUtils.getString(bodyParam, + TAG); + String msg = MapUtils.getString(bodyParam, + MSG); + String ttl = MapUtils.getString(bodyParam, + TTL); + SendMessageBatchV2RequestBody body = new SendMessageBatchV2RequestBody(); + body.setBizSeqNo(bizSeqno); + body.setMsg(msg); + body.setTag(tag); + body.setTtl(ttl); + body.setTopic(topic); + body.setProducerGroup(MapUtils.getString(bodyParam, PRODUCERGROUP)); + return body; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(BIZSEQNO, bizSeqNo); + map.put(TOPIC, topic); + map.put(MSG, msg); + map.put(TAG, tag); + map.put(TTL, ttl); + map.put(PRODUCERGROUP, producerGroup); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("SendMessageBatchV2RequestBody={") + .append("bizSeqNo=").append(bizSeqNo).append(",") + .append("topic=").append(topic).append(",") + .append("tag=").append(tag).append(",") + .append("ttl=").append(ttl).append(",") + .append("producerGroup=").append(producerGroup).append(",") + .append("msg=").append(msg).append("}"); + return sb.toString(); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageBatchV2ResponseBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageBatchV2ResponseBody.java new file mode 100644 index 0000000000..26cc08202c --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageBatchV2ResponseBody.java @@ -0,0 +1,90 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.message; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.apache.commons.lang3.time.DateFormatUtils; + +import java.util.HashMap; +import java.util.Map; + +public class SendMessageBatchV2ResponseBody extends Body { + + //return code + private Integer retCode; + + //response message + private String retMsg; + + //response time + private long resTime = System.currentTimeMillis(); + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getRetMsg() { + return retMsg; + } + + public void setRetMsg(String retMsg) { + this.retMsg = retMsg; + } + + public long getResTime() { + return resTime; + } + + public void setResTime(long resTime) { + this.resTime = resTime; + } + + public static SendMessageBatchV2ResponseBody buildBody(Integer retCode, String retMsg) { + SendMessageBatchV2ResponseBody sendMessageBatchV2ResponseBody = new SendMessageBatchV2ResponseBody(); + sendMessageBatchV2ResponseBody.setRetMsg(retMsg); + sendMessageBatchV2ResponseBody.setRetCode(retCode); + sendMessageBatchV2ResponseBody.setResTime(System.currentTimeMillis()); + return sendMessageBatchV2ResponseBody; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("sendMessageBatchV2ResponseBody={") + .append("retCode=").append(retCode).append(",") + .append("retMsg=").append(retMsg).append(",") + .append("resTime=").append(DateFormatUtils.format(resTime, Constants.DATE_FORMAT)).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(ProtocolKey.RETCODE, retCode); + map.put(ProtocolKey.RETMSG, retMsg); + map.put(ProtocolKey.RESTIME, resTime); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageRequestBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageRequestBody.java new file mode 100644 index 0000000000..66f3d8979e --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageRequestBody.java @@ -0,0 +1,169 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.message; + +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.utils.JsonUtils; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.core.type.TypeReference; + +public class SendMessageRequestBody extends Body { + + public static final String TOPIC = "topic"; + public static final String BIZSEQNO = "bizseqno"; + public static final String UNIQUEID = "uniqueid"; + public static final String CONTENT = "content"; + public static final String TTL = "ttl"; + public static final String TAG = "tag"; + public static final String EXTFIELDS = "extFields"; + public static final String PRODUCERGROUP = "producergroup"; + + private String topic; + + private String bizSeqNo; + + private String uniqueId; + + private String ttl; + + private String content; + + private String tag; + + private Map extFields; + + private String producerGroup; + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public String getBizSeqNo() { + return bizSeqNo; + } + + public void setBizSeqNo(String bizSeqNo) { + this.bizSeqNo = bizSeqNo; + } + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Map getExtFields() { + return extFields; + } + + public void setExtFields(Map extFields) { + this.extFields = extFields; + } + + public String getTtl() { + return ttl; + } + + public void setTtl(String ttl) { + this.ttl = ttl; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public String getProducerGroup() { + return producerGroup; + } + + public void setProducerGroup(String producerGroup) { + this.producerGroup = producerGroup; + } + + public static SendMessageRequestBody buildBody(Map bodyParam) { + SendMessageRequestBody body = new SendMessageRequestBody(); + body.setTopic(MapUtils.getString(bodyParam, TOPIC)); + body.setBizSeqNo(MapUtils.getString(bodyParam, BIZSEQNO)); + body.setUniqueId(MapUtils.getString(bodyParam, UNIQUEID)); + body.setTtl(MapUtils.getString(bodyParam, TTL)); + body.setTag(MapUtils.getString(bodyParam, TAG, "")); + body.setContent(MapUtils.getString(bodyParam, CONTENT)); + String extFields = MapUtils.getString(bodyParam, EXTFIELDS); + if (StringUtils.isNotBlank(extFields)) { + body.setExtFields( + JsonUtils.deserialize(extFields, new TypeReference>() { + })); + } + body.setProducerGroup(MapUtils.getString(bodyParam, PRODUCERGROUP)); + return body; + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(TOPIC, topic); + map.put(BIZSEQNO, bizSeqNo); + map.put(UNIQUEID, uniqueId); + map.put(TTL, ttl); + map.put(TAG, tag); + map.put(CONTENT, content); + map.put(EXTFIELDS, extFields); + map.put(PRODUCERGROUP, producerGroup); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("sendMessageRequestBody={") + .append("topic=").append(topic).append(",") + .append("bizSeqNo=").append(bizSeqNo).append(",") + .append("uniqueId=").append(uniqueId).append(",") + .append("content=").append(content).append(",") + .append("ttl=").append(ttl).append(",") + .append("tag=").append(tag).append(",") + .append("producerGroup=").append(producerGroup).append(",") + .append("extFields=").append(extFields).append("}"); + return sb.toString(); + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageResponseBody.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageResponseBody.java new file mode 100644 index 0000000000..e4e9eaa120 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/body/message/SendMessageResponseBody.java @@ -0,0 +1,98 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body.message; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.apache.commons.lang3.time.DateFormatUtils; + +import java.util.HashMap; +import java.util.Map; + +import lombok.Builder; +import lombok.Data; + +public class SendMessageResponseBody extends Body { + + private Integer retCode; + + private String retMsg; + + private long resTime = System.currentTimeMillis(); + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getRetMsg() { + return retMsg; + } + + public void setRetMsg(String retMsg) { + this.retMsg = retMsg; + } + + public long getResTime() { + return resTime; + } + + public void setResTime(long resTime) { + this.resTime = resTime; + } + + public static SendMessageResponseBody buildBody(Integer retCode, String retMsg) { + SendMessageResponseBody sendMessageResponseBody = new SendMessageResponseBody(); + sendMessageResponseBody.setRetMsg(retMsg); + sendMessageResponseBody.setResTime(System.currentTimeMillis()); + sendMessageResponseBody.setRetCode(retCode); + return sendMessageResponseBody; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("sendMessageResponseBody={") + .append("retCode=").append(retCode).append(",") + .append("retMsg=").append(retMsg).append(",") + .append("resTime=").append(DateFormatUtils.format(resTime, Constants.DATE_FORMAT)).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(ProtocolKey.RETCODE, retCode); + map.put(ProtocolKey.RETMSG, retMsg); + map.put(ProtocolKey.RESTIME, resTime); + return map; + } + + @Data + @Builder + public static class ReplyMessage { + public String topic; + public String body; + public Map properties; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/ClientRetCode.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/ClientRetCode.java new file mode 100644 index 0000000000..ceaf05cef2 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/ClientRetCode.java @@ -0,0 +1,79 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.common; + +public enum ClientRetCode { + + /** + * The "RETRY" means:when the client finds the delivered message and it does not listen, tell EventMesh to send + * next, try again several times to achieve grayscale, reserve + */ + + REMOTE_OK(0, "REMOTE Process OK"), + OK(1, "OK. SDK returns."), + RETRY(2, "RETRY. SDK returns. Retry at most max(default, config) times."), + FAIL(3, "FAIL. SDK returns."), + NOLISTEN(5, "NOLISTEN. SDK returns. It can be used for grayscale publishing. Need to try all URLs in this case."); + + ClientRetCode(Integer retCode, String errMsg) { + this.retCode = retCode; + this.errMsg = errMsg; + } + + public static boolean contains(Integer clientRetCode) { + boolean flag = false; + for (ClientRetCode itr : ClientRetCode.values()) { + if (itr.retCode.intValue() == clientRetCode.intValue()) { + flag = true; + break; + } + } + return flag; + } + + public static ClientRetCode get(Integer clientRetCode) { + ClientRetCode ret = null; + for (ClientRetCode itr : ClientRetCode.values()) { + if (itr.retCode.intValue() == clientRetCode.intValue()) { + ret = itr; + break; + } + } + return ret; + } + + private Integer retCode; + + private String errMsg; + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getErrMsg() { + return errMsg; + } + + public void setErrMsg(String errMsg) { + this.errMsg = errMsg; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/ClientType.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/ClientType.java new file mode 100644 index 0000000000..c935da6cc4 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/ClientType.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.common; + +public enum ClientType { + + PUB(1, "Client for publishing"), + + SUB(2, "Client for subscribing"); + + private Integer type; + + private String desc; + + ClientType(Integer type, String desc) { + this.type = type; + this.desc = desc; + } + + public static ClientType get(Integer type) { + if (PUB.type.intValue() == type.intValue()) { + return PUB; + } else if (SUB.type.intValue() == type.intValue()) { + return SUB; + } else { + return null; + } + } + + public static boolean contains(Integer clientType) { + boolean flag = false; + for (ClientType ct : ClientType.values()) { + if (ct.type == clientType.intValue()) { + flag = true; + break; + } + } + return flag; + } + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/EventMeshRetCode.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/EventMeshRetCode.java new file mode 100644 index 0000000000..831eaaca6a --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/EventMeshRetCode.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.common; + +public enum EventMeshRetCode { + + SUCCESS(0, "success"), + OVERLOAD(1, "eventMesh overload, try later, "), + EVENTMESH_REQUESTCODE_INVALID(2, "requestCode can't be null, or must be number, "), + EVENTMESH_SEND_SYNC_MSG_ERR(3, "eventMesh send rr msg err, "), + EVENTMESH_WAITING_RR_MSG_ERR(4, "eventMesh waiting rr msg err, "), + EVENTMESH_PROTOCOL_HEADER_ERR(6, "eventMesh protocol[header] err, "), + EVENTMESH_PROTOCOL_BODY_ERR(7, "eventMesh protocol[body] err, "), + EVENTMESH_PROTOCOL_BODY_SIZE_ERR(8, "event size exceeds the limit, "), + EVENTMESH_STOP(9, "eventMesh will stop or had stopped, "), + EVENTMESH_REJECT_BY_PROCESSOR_ERROR(10, "eventMesh reject by processor error, "), + EVENTMESH_BATCH_PRODUCER_STOPED_ERR(11, "eventMesh batch msg producer stopped, "), + EVENTMESH_BATCH_SPEED_OVER_LIMIT_ERR(12, "eventMesh batch msg speed over the limit, "), + EVENTMESH_PACKAGE_MSG_ERR(13, "eventMesh package msg err, "), + EVENTMESH_GROUP_PRODUCER_STOPED_ERR(14, "eventMesh group producer stopped, "), + EVENTMESH_SEND_ASYNC_MSG_ERR(15, "eventMesh send async msg err, "), + EVENTMESH_REPLY_MSG_ERR(16, "eventMesh reply msg err, "), + EVENTMESH_SEND_BATCHLOG_MSG_ERR(17, "eventMesh send batchlog msg err, "), + EVENTMESH_RUNTIME_ERR(18, "eventMesh runtime err, "), + EVENTMESH_SUBSCRIBE_ERR(19, "eventMesh subscribe err"), + EVENTMESH_UNSUBSCRIBE_ERR(20, "eventMesh unsubscribe err"), + EVENTMESH_HEARTBEAT_ERR(21, "eventMesh heartbeat err"), + EVENTMESH_ACL_ERR(22, "eventMesh acl err"), + EVENTMESH_HTTP_MES_SEND_OVER_LIMIT_ERR(23, "eventMesh http msg send over the limit, "); + + private Integer retCode; + + private String errMsg; + + EventMeshRetCode(Integer retCode, String errMsg) { + this.retCode = retCode; + this.errMsg = errMsg; + } + + public Integer getRetCode() { + return retCode; + } + + public void setRetCode(Integer retCode) { + this.retCode = retCode; + } + + public String getErrMsg() { + return errMsg; + } + + public void setErrMsg(String errMsg) { + this.errMsg = errMsg; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/ProtocolKey.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/ProtocolKey.java new file mode 100644 index 0000000000..19a836ae3a --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/ProtocolKey.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.common; + +public class ProtocolKey { + + public static final String REQUEST_CODE = "code"; + public static final String REQUEST_URI = "uri"; + public static final String LANGUAGE = "language"; + public static final String VERSION = "version"; + + public static final String PROTOCOL_TYPE = "protocoltype"; + + public static final String PROTOCOL_VERSION = "protocolversion"; + + public static final String PROTOCOL_DESC = "protocoldesc"; + + public static final String CONTENT_TYPE = "contenttype"; + + public static class ClientInstanceKey { + ////////////////////////////////////Protocol layer requester description/////////// + public static final String ENV = "env"; + public static final String IDC = "idc"; + public static final String SYS = "sys"; + public static final String PID = "pid"; + public static final String IP = "ip"; + public static final String USERNAME = "username"; + public static final String PASSWD = "passwd"; + public static final String BIZSEQNO = "bizseqno"; + public static final String UNIQUEID = "uniqueid"; + public static final String PRODUCERGROUP = "producergroup"; + public static final String CONSUMERGROUP = "consumergroup"; + } + + + public static class EventMeshInstanceKey { + ///////////////////////////////////////////////Protocol layer EventMesh description + public static final String EVENTMESHCLUSTER = "eventmeshcluster"; + public static final String EVENTMESHIP = "eventmeship"; + public static final String EVENTMESHENV = "eventmeshenv"; + public static final String EVENTMESHIDC = "eventmeshidc"; + } + + public static class CloudEventsKey { + public static final String ID = "id"; + public static final String SOURCE = "source"; + public static final String SUBJECT = "subject"; + public static final String TYPE = "type"; + } + + + //return of CLIENT <-> EventMesh + public static final String RETCODE = "retCode"; + public static final String RETMSG = "retMsg"; + public static final String RESTIME = "resTime"; +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/ProtocolVersion.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/ProtocolVersion.java new file mode 100644 index 0000000000..acfd655246 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/ProtocolVersion.java @@ -0,0 +1,59 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.common; + +public enum ProtocolVersion { + + V1("1.0"), + V2("2.0"); + + private String version; + + ProtocolVersion(String version) { + this.version = version; + } + + public static ProtocolVersion get(String version) { + if (V1.version.equals(version)) { + return V1; + } else if (V2.version.equals(version)) { + return V2; + } else { + return null; + } + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public static boolean contains(String version) { + boolean flag = false; + for (ProtocolVersion itr : ProtocolVersion.values()) { + if (itr.version.equals(version)) { + flag = true; + break; + } + } + return flag; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/RequestCode.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/RequestCode.java new file mode 100644 index 0000000000..32e1b7fbcc --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/RequestCode.java @@ -0,0 +1,96 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.common; + +public enum RequestCode { + + MSG_BATCH_SEND(102, "SEND BATCH MSG"), + + MSG_BATCH_SEND_V2(107, "SEND BATCH MSG V2"), + + MSG_SEND_SYNC(101, "SEND SINGLE MSG SYNC"), + + MSG_SEND_ASYNC(104, "SEND SINGLE MSG ASYNC"), + + HTTP_PUSH_CLIENT_ASYNC(105, "PUSH CLIENT BY HTTP POST"), + + HTTP_PUSH_CLIENT_SYNC(106, "PUSH CLIENT BY HTTP POST"), + + REGISTER(201, "REGISTER"), + + UNREGISTER(202, "UNREGISTER"), + + HEARTBEAT(203, "HEARTBEAT"), + + SUBSCRIBE(206, "SUBSCRIBE"), + + UNSUBSCRIBE(207, "UNSUBSCRIBE"), + + REPLY_MESSAGE(301, "REPLY MESSAGE"), + + ADMIN_METRICS(603, "ADMIN METRICS"), + + ADMIN_SHUTDOWN(601, "ADMIN SHUTDOWN"); + + private Integer requestCode; + + private String desc; + + RequestCode(Integer requestCode, String desc) { + this.requestCode = requestCode; + this.desc = desc; + } + + public static boolean contains(Integer requestCode) { + boolean flag = false; + for (RequestCode itr : RequestCode.values()) { + if (itr.requestCode.intValue() == requestCode.intValue()) { + flag = true; + break; + } + } + return flag; + } + + public static RequestCode get(Integer requestCode) { + RequestCode ret = null; + for (RequestCode itr : RequestCode.values()) { + if (itr.requestCode.intValue() == requestCode.intValue()) { + ret = itr; + break; + } + } + return ret; + } + + public Integer getRequestCode() { + return requestCode; + } + + public void setRequestCode(Integer requestCode) { + this.requestCode = requestCode; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/RequestURI.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/RequestURI.java new file mode 100644 index 0000000000..ff295c30a6 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/common/RequestURI.java @@ -0,0 +1,83 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.common; + +public enum RequestURI { + + PUBLISH("/eventmesh/publish", "PUBLISH SINGLE EVENT"), + + PUBLISH_BRIDGE("/eventmesh/bridge/publish", "PUBLISH REMOTE SINGLE EVENT"), + + PUBLISH_BATCH("/eventmesh/publish/batch", "PUBLISH BATCH EVENTS"), + + SUBSCRIBE_LOCAL("/eventmesh/subscribe/local", "SUBSCRIBE LOCAL"), + + SUBSCRIBE_REMOTE("/eventmesh/subscribe/remote", "SUBSCRIBE REMOTE"), + + UNSUBSCRIBE_LOCAL("/eventmesh/unsubscribe/local", "SUBSCRIBE LOCAL"), + + UNSUBSCRIBE_REMOTE("/eventmesh/unsubscribe/remote", "SUBSCRIBE REMOTE"); + + + private String requestURI; + + private String desc; + + RequestURI(String requestURI, String desc) { + this.requestURI = requestURI; + this.desc = desc; + } + + public static boolean contains(String requestURI) { + boolean flag = false; + for (RequestURI itr : RequestURI.values()) { + if (itr.requestURI.equals(requestURI)) { + flag = true; + break; + } + } + return flag; + } + + public static RequestURI get(String requestURI) { + RequestURI ret = null; + for (RequestURI itr : RequestURI.values()) { + if (itr.requestURI.equals(requestURI)) { + ret = itr; + break; + } + } + return ret; + } + + public String getRequestURI() { + return requestURI; + } + + public void setRequestURI(String requestURI) { + this.requestURI = requestURI; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/BaseRequestHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/BaseRequestHeader.java new file mode 100644 index 0000000000..f34f915418 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/BaseRequestHeader.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header; + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.apache.commons.collections4.MapUtils; + +import java.util.HashMap; +import java.util.Map; + +public class BaseRequestHeader extends Header { + private String code; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public static BaseRequestHeader buildHeader(Map headerParam) { + BaseRequestHeader header = new BaseRequestHeader(); + header.setCode(MapUtils.getString(headerParam, ProtocolKey.REQUEST_CODE)); + return header; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("baseRequestHeader={code=") + .append(code).append("}"); + return sb.toString(); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/BaseResponseHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/BaseResponseHeader.java new file mode 100644 index 0000000000..2a2e2c7665 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/BaseResponseHeader.java @@ -0,0 +1,50 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header; + + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import java.util.HashMap; +import java.util.Map; + +public class BaseResponseHeader extends Header { + + private String code; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public static BaseResponseHeader buildHeader(String code) { + BaseResponseHeader baseResponseHeader = new BaseResponseHeader(); + baseResponseHeader.setCode(code); + return baseResponseHeader; + } + + @Override + public Map toMap() { + Map map = new HashMap<>(); + map.put(ProtocolKey.REQUEST_CODE, code); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/Header.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/Header.java new file mode 100644 index 0000000000..9a432202a1 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/Header.java @@ -0,0 +1,72 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header; + + +import org.apache.eventmesh.common.protocol.http.common.RequestCode; +import org.apache.eventmesh.common.protocol.http.header.client.HeartbeatRequestHeader; +import org.apache.eventmesh.common.protocol.http.header.client.RegRequestHeader; +import org.apache.eventmesh.common.protocol.http.header.client.SubscribeRequestHeader; +import org.apache.eventmesh.common.protocol.http.header.client.UnRegRequestHeader; +import org.apache.eventmesh.common.protocol.http.header.client.UnSubscribeRequestHeader; +import org.apache.eventmesh.common.protocol.http.header.message.PushMessageRequestHeader; +import org.apache.eventmesh.common.protocol.http.header.message.ReplyMessageRequestHeader; +import org.apache.eventmesh.common.protocol.http.header.message.SendMessageBatchRequestHeader; +import org.apache.eventmesh.common.protocol.http.header.message.SendMessageBatchV2RequestHeader; +import org.apache.eventmesh.common.protocol.http.header.message.SendMessageRequestHeader; + +import java.util.Map; + +public abstract class Header { + + public abstract Map toMap(); + + public static Header buildHeader(String requestCode, Map originalMap) throws Exception { + if (String.valueOf(RequestCode.MSG_BATCH_SEND.getRequestCode()).equals(requestCode)) { + return SendMessageBatchRequestHeader.buildHeader(originalMap); + } + if (String.valueOf(RequestCode.MSG_BATCH_SEND_V2.getRequestCode()).equals(requestCode)) { + return SendMessageBatchV2RequestHeader.buildHeader(originalMap); + } else if (String.valueOf(RequestCode.MSG_SEND_SYNC.getRequestCode()).equals(requestCode)) { + return SendMessageRequestHeader.buildHeader(originalMap); + } else if (String.valueOf(RequestCode.MSG_SEND_ASYNC.getRequestCode()).equals(requestCode)) { + return SendMessageRequestHeader.buildHeader(originalMap); + } else if (String.valueOf(RequestCode.HTTP_PUSH_CLIENT_ASYNC.getRequestCode()).equals(requestCode)) { + return PushMessageRequestHeader.buildHeader(originalMap); + } else if (String.valueOf(RequestCode.HTTP_PUSH_CLIENT_SYNC.getRequestCode()).equals(requestCode)) { + return PushMessageRequestHeader.buildHeader(originalMap); + } else if (String.valueOf(RequestCode.REGISTER.getRequestCode()).equals(requestCode)) { + return RegRequestHeader.buildHeader(originalMap); + } else if (String.valueOf(RequestCode.UNREGISTER.getRequestCode()).equals(requestCode)) { + return UnRegRequestHeader.buildHeader(originalMap); + } else if (String.valueOf(RequestCode.SUBSCRIBE.getRequestCode()).equals(requestCode)) { + return SubscribeRequestHeader.buildHeader(originalMap); + } else if (String.valueOf(RequestCode.UNSUBSCRIBE.getRequestCode()).equals(requestCode)) { + return UnSubscribeRequestHeader.buildHeader(originalMap); + } else if (String.valueOf(RequestCode.HEARTBEAT.getRequestCode()).equals(requestCode)) { + return HeartbeatRequestHeader.buildHeader(originalMap); + } else if (String.valueOf(RequestCode.REPLY_MESSAGE.getRequestCode()).equals(requestCode)) { + return ReplyMessageRequestHeader.buildHeader(originalMap); + } else if (String.valueOf(RequestCode.ADMIN_SHUTDOWN.getRequestCode()).equals(requestCode)) { + return BaseRequestHeader.buildHeader(originalMap); + } else { + throw new Exception(); + } + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/HeartbeatRequestHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/HeartbeatRequestHeader.java new file mode 100644 index 0000000000..22f202a546 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/HeartbeatRequestHeader.java @@ -0,0 +1,194 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +public class HeartbeatRequestHeader extends Header { + + //request code + private String code; + + //requester language description + private String language; + + //protocol version adopted by requester, default:1.0 + private ProtocolVersion version; + + //the environment number of the requester + private String env; + + //the IDC of the requester + private String idc; + + //subsystem of the requester + private String sys; + + //PID of the requester + private String pid; + + //IP of the requester + private String ip; + + //private String producerGroup; + + //USERNAME of the requester + private String username = "username"; + + //PASSWD of the requester + private String passwd = "user@123"; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public ProtocolVersion getVersion() { + return version; + } + + public void setVersion(ProtocolVersion version) { + this.version = version; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getIdc() { + return idc; + } + + public void setIdc(String idc) { + this.idc = idc; + } + + public String getSys() { + return sys; + } + + public void setSys(String sys) { + this.sys = sys; + } + + public String getPid() { + return pid; + } + + public void setPid(String pid) { + this.pid = pid; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPasswd() { + return passwd; + } + + public void setPasswd(String passwd) { + this.passwd = passwd; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.LANGUAGE, language); + map.put(ProtocolKey.VERSION, version); + map.put(ProtocolKey.ClientInstanceKey.ENV, env); + map.put(ProtocolKey.ClientInstanceKey.IDC, idc); + map.put(ProtocolKey.ClientInstanceKey.SYS, sys); + map.put(ProtocolKey.ClientInstanceKey.PID, pid); + map.put(ProtocolKey.ClientInstanceKey.IP, ip); + map.put(ProtocolKey.ClientInstanceKey.USERNAME, username); + map.put(ProtocolKey.ClientInstanceKey.PASSWD, passwd); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("heartbeatRequestHeader={") + .append("code=").append(code).append(",") + .append("language=").append(language).append(",") + .append("version=").append(version).append(",") + .append("env=").append(env).append(",") + .append("idc=").append(idc).append(",") + .append("sys=").append(sys).append(",") + .append("pid=").append(pid).append(",") + .append("ip=").append(ip).append(",") + .append("username=").append(username).append(",") + .append("passwd=").append(passwd).append("}"); + return sb.toString(); + } + + public static HeartbeatRequestHeader buildHeader(Map headerParam) { + HeartbeatRequestHeader header = new HeartbeatRequestHeader(); + header.setCode(MapUtils.getString(headerParam, ProtocolKey.REQUEST_CODE)); + header.setVersion(ProtocolVersion.get(MapUtils.getString(headerParam, ProtocolKey.VERSION))); + String lan = StringUtils.isBlank(MapUtils.getString(headerParam, ProtocolKey.LANGUAGE)) + ? Constants.LANGUAGE_JAVA : MapUtils.getString(headerParam, ProtocolKey.LANGUAGE); + header.setLanguage(lan); + header.setEnv(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.ENV)); + header.setIdc(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IDC)); + header.setSys(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.SYS)); + header.setPid(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PID)); + header.setIp(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IP)); + header.setUsername(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.USERNAME)); + header.setPasswd(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PASSWD)); + return header; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/HeartbeatResponseHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/HeartbeatResponseHeader.java new file mode 100644 index 0000000000..c1c35c47d1 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/HeartbeatResponseHeader.java @@ -0,0 +1,113 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import java.util.HashMap; +import java.util.Map; + +public class HeartbeatResponseHeader extends Header { + + private int code; + + private String eventMeshCluster; + + private String eventMeshIp; + + private String eventMeshEnv; + + private String eventMeshIdc; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getEventMeshCluster() { + return eventMeshCluster; + } + + public void setEventMeshCluster(String eventMeshCluster) { + this.eventMeshCluster = eventMeshCluster; + } + + public String getEventMeshIp() { + return eventMeshIp; + } + + public void setEventMeshIp(String eventMeshIp) { + this.eventMeshIp = eventMeshIp; + } + + public String getEventMeshEnv() { + return eventMeshEnv; + } + + public void setEventMeshEnv(String eventMeshEnv) { + this.eventMeshEnv = eventMeshEnv; + } + + public String getEventMeshIdc() { + return eventMeshIdc; + } + + public void setEventMeshIdc(String eventMeshIdc) { + this.eventMeshIdc = eventMeshIdc; + } + + public static HeartbeatResponseHeader buildHeader(Integer requestCode, String eventMeshCluster, + String eventMeshIp, String eventMeshEnv, + String eventMeshIDC) { + HeartbeatResponseHeader heartbeatResponseHeader = new HeartbeatResponseHeader(); + heartbeatResponseHeader.setCode(requestCode); + heartbeatResponseHeader.setEventMeshCluster(eventMeshCluster); + heartbeatResponseHeader.setEventMeshIp(eventMeshIp); + heartbeatResponseHeader.setEventMeshEnv(eventMeshEnv); + heartbeatResponseHeader.setEventMeshIdc(eventMeshIDC); + return heartbeatResponseHeader; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("heartbeatResponseHeader={") + .append("code=").append(code).append(",") + .append("eventMeshEnv=").append(eventMeshEnv).append(",") + .append("eventMeshIdc=").append(eventMeshIdc).append(",") + .append("eventMeshCluster=").append(eventMeshCluster).append(",") + .append("eventMeshIp=").append(eventMeshIp).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER, eventMeshCluster); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP, eventMeshIp); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV, eventMeshEnv); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC, eventMeshIdc); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/RegRequestHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/RegRequestHeader.java new file mode 100644 index 0000000000..3d88dbf312 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/RegRequestHeader.java @@ -0,0 +1,182 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +public class RegRequestHeader extends Header { + + private String code; + + private String language; + + private ProtocolVersion version; + + private String env; + + private String idc; + + private String sys; + + private String pid; + + private String ip; + + private String username; + + private String passwd; + + public static RegRequestHeader buildHeader(Map headerParam) { + RegRequestHeader header = new RegRequestHeader(); + header.setCode(MapUtils.getString(headerParam, ProtocolKey.REQUEST_CODE)); + header.setVersion(ProtocolVersion.get(MapUtils.getString(headerParam, ProtocolKey.VERSION))); + String lan = StringUtils.isBlank(MapUtils.getString(headerParam, ProtocolKey.LANGUAGE)) + ? Constants.LANGUAGE_JAVA : MapUtils.getString(headerParam, ProtocolKey.LANGUAGE); + header.setLanguage(lan); + header.setEnv(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.ENV)); + header.setIdc(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IDC)); + header.setSys(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.SYS)); + header.setPid(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PID)); + header.setIp(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IP)); + header.setUsername(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.USERNAME)); + header.setPasswd(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PASSWD)); + return header; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public ProtocolVersion getVersion() { + return version; + } + + public void setVersion(ProtocolVersion version) { + this.version = version; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getIdc() { + return idc; + } + + public void setIdc(String idc) { + this.idc = idc; + } + + public String getSys() { + return sys; + } + + public void setSys(String sys) { + this.sys = sys; + } + + public String getPid() { + return pid; + } + + public void setPid(String pid) { + this.pid = pid; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPasswd() { + return passwd; + } + + public void setPasswd(String passwd) { + this.passwd = passwd; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.LANGUAGE, language); + map.put(ProtocolKey.VERSION, version); + map.put(ProtocolKey.ClientInstanceKey.ENV, env); + map.put(ProtocolKey.ClientInstanceKey.IDC, idc); + map.put(ProtocolKey.ClientInstanceKey.SYS, sys); + map.put(ProtocolKey.ClientInstanceKey.PID, pid); + map.put(ProtocolKey.ClientInstanceKey.IP, ip); + map.put(ProtocolKey.ClientInstanceKey.USERNAME, username); + map.put(ProtocolKey.ClientInstanceKey.PASSWD, passwd); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("regRequestHeader={") + .append("code=").append(code).append(",") + .append("language=").append(language).append(",") + .append("version=").append(version).append(",") + .append("env=").append(env).append(",") + .append("idc=").append(idc).append(",") + .append("sys=").append(sys).append(",") + .append("pid=").append(pid).append(",") + .append("ip=").append(ip).append(",") + .append("username=").append(username).append(",") + .append("passwd=").append(passwd).append("}"); + return sb.toString(); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/RegResponseHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/RegResponseHeader.java new file mode 100644 index 0000000000..b928b79fd0 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/RegResponseHeader.java @@ -0,0 +1,118 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import java.util.HashMap; +import java.util.Map; + +public class RegResponseHeader extends Header { + + //response code, as same as the request code + private int code; + + //The cluster name of the EventMesh that processes the request + private String eventMeshCluster; + + //IP of the EventMesh that processes the request + private String eventMeshIp; + + //Environment number of the EventMesh that processes the request + private String eventMeshEnv; + + //IDC of the EventMesh that processes the request + private String eventMeshIdc; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getEventMeshCluster() { + return eventMeshCluster; + } + + public void setEventMeshCluster(String eventMeshCluster) { + this.eventMeshCluster = eventMeshCluster; + } + + public String getEventMeshIp() { + return eventMeshIp; + } + + public void setEventMeshIp(String eventMeshIp) { + this.eventMeshIp = eventMeshIp; + } + + public String getEventMeshEnv() { + return eventMeshEnv; + } + + public void setEventMeshEnv(String eventMeshEnv) { + this.eventMeshEnv = eventMeshEnv; + } + + public String getEventMeshIdc() { + return eventMeshIdc; + } + + public void setEventMeshIdc(String eventMeshIdc) { + this.eventMeshIdc = eventMeshIdc; + } + + public static RegResponseHeader buildHeader(Integer requestCode, String eventMeshCluster, + String eventMeshIp, String eventMeshEnv, String eventMeshIDC) { + RegResponseHeader regResponseHeader = new RegResponseHeader(); + regResponseHeader.setCode(requestCode); + regResponseHeader.setEventMeshCluster(eventMeshCluster); + regResponseHeader.setEventMeshIp(eventMeshIp); + regResponseHeader.setEventMeshEnv(eventMeshEnv); + regResponseHeader.setEventMeshIdc(eventMeshIDC); + return regResponseHeader; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("regResponseHeader={") + .append("code=").append(code).append(",") + .append("eventMeshEnv=").append(eventMeshEnv).append(",") + .append("eventMeshIdc=").append(eventMeshIdc).append(",") + .append("eventMeshCluster=").append(eventMeshCluster).append(",") + .append("eventMeshIp=").append(eventMeshIp).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER, eventMeshCluster); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP, eventMeshIp); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV, eventMeshEnv); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC, eventMeshIdc); + return map; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/SubscribeRequestHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/SubscribeRequestHeader.java new file mode 100644 index 0000000000..adef902d93 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/SubscribeRequestHeader.java @@ -0,0 +1,182 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +public class SubscribeRequestHeader extends Header { + + private String code; + + private String language; + + private ProtocolVersion version; + + private String env; + + private String idc; + + private String sys; + + private String pid; + + private String ip; + + private String username; + + private String passwd; + + public static SubscribeRequestHeader buildHeader(Map headerParam) { + SubscribeRequestHeader header = new SubscribeRequestHeader(); + header.setCode(MapUtils.getString(headerParam, ProtocolKey.REQUEST_CODE)); + header.setVersion(ProtocolVersion.get(MapUtils.getString(headerParam, ProtocolKey.VERSION))); + String lan = StringUtils.isBlank(MapUtils.getString(headerParam, ProtocolKey.LANGUAGE)) + ? Constants.LANGUAGE_JAVA : MapUtils.getString(headerParam, ProtocolKey.LANGUAGE); + header.setLanguage(lan); + header.setEnv(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.ENV)); + header.setIdc(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IDC)); + header.setSys(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.SYS)); + header.setPid(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PID)); + header.setIp(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IP)); + header.setUsername(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.USERNAME)); + header.setPasswd(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PASSWD)); + return header; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public ProtocolVersion getVersion() { + return version; + } + + public void setVersion(ProtocolVersion version) { + this.version = version; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getIdc() { + return idc; + } + + public void setIdc(String idc) { + this.idc = idc; + } + + public String getSys() { + return sys; + } + + public void setSys(String sys) { + this.sys = sys; + } + + public String getPid() { + return pid; + } + + public void setPid(String pid) { + this.pid = pid; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPasswd() { + return passwd; + } + + public void setPasswd(String passwd) { + this.passwd = passwd; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.LANGUAGE, language); + map.put(ProtocolKey.VERSION, version); + map.put(ProtocolKey.ClientInstanceKey.ENV, env); + map.put(ProtocolKey.ClientInstanceKey.IDC, idc); + map.put(ProtocolKey.ClientInstanceKey.SYS, sys); + map.put(ProtocolKey.ClientInstanceKey.PID, pid); + map.put(ProtocolKey.ClientInstanceKey.IP, ip); + map.put(ProtocolKey.ClientInstanceKey.USERNAME, username); + map.put(ProtocolKey.ClientInstanceKey.PASSWD, passwd); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("subscribeRequestHeader={") + .append("code=").append(code).append(",") + .append("language=").append(language).append(",") + .append("version=").append(version).append(",") + .append("env=").append(env).append(",") + .append("idc=").append(idc).append(",") + .append("sys=").append(sys).append(",") + .append("pid=").append(pid).append(",") + .append("ip=").append(ip).append(",") + .append("username=").append(username).append(",") + .append("passwd=").append(passwd).append("}"); + return sb.toString(); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/SubscribeResponseHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/SubscribeResponseHeader.java new file mode 100644 index 0000000000..d16fb4e6aa --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/SubscribeResponseHeader.java @@ -0,0 +1,113 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import java.util.HashMap; +import java.util.Map; + +public class SubscribeResponseHeader extends Header { + + private int code; + + private String eventMeshCluster; + + private String eventMeshIp; + + private String eventMeshEnv; + + private String eventMeshIdc; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getEventMeshCluster() { + return eventMeshCluster; + } + + public void setEventMeshCluster(String eventMeshCluster) { + this.eventMeshCluster = eventMeshCluster; + } + + public String getEventMeshIp() { + return eventMeshIp; + } + + public void setEventMeshIp(String eventMeshIp) { + this.eventMeshIp = eventMeshIp; + } + + public String getEventMeshEnv() { + return eventMeshEnv; + } + + public void setEventMeshEnv(String eventMeshEnv) { + this.eventMeshEnv = eventMeshEnv; + } + + public String getEventMeshIdc() { + return eventMeshIdc; + } + + public void setEventMeshIdc(String eventMeshIdc) { + this.eventMeshIdc = eventMeshIdc; + } + + public static SubscribeResponseHeader buildHeader(Integer requestCode, String eventMeshCluster, + String eventMeshIp, String eventMeshEnv, + String eventMeshIDC) { + SubscribeResponseHeader subscribeResponseHeader = new SubscribeResponseHeader(); + subscribeResponseHeader.setCode(requestCode); + subscribeResponseHeader.setEventMeshCluster(eventMeshCluster); + subscribeResponseHeader.setEventMeshIp(eventMeshIp); + subscribeResponseHeader.setEventMeshEnv(eventMeshEnv); + subscribeResponseHeader.setEventMeshIdc(eventMeshIDC); + return subscribeResponseHeader; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("subscribeResponseHeader={") + .append("code=").append(code).append(",") + .append("eventMeshEnv=").append(eventMeshEnv).append(",") + .append("eventMeshIdc=").append(eventMeshIdc).append(",") + .append("eventMeshCluster=").append(eventMeshCluster).append(",") + .append("eventMeshIp=").append(eventMeshIp).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER, eventMeshCluster); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP, eventMeshIp); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV, eventMeshEnv); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC, eventMeshIdc); + return map; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/UnRegRequestHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/UnRegRequestHeader.java new file mode 100644 index 0000000000..639d696476 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/UnRegRequestHeader.java @@ -0,0 +1,193 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +public class UnRegRequestHeader extends Header { + + //request code + private String code; + + //requester language description + private String language; + + //protocol version adopted by requester, default:1.0 + private ProtocolVersion version; + + //the environment number of the requester + private String env; + + //the IDC of the requester + private String idc; + + //subsystem of the requester + private String sys; + + //PID of the requester + private String pid; + + //IP of the requester + private String ip; + + //USERNAME of the requester + private String username = "username"; + + //PASSWD of the requester + private String passwd = "user@123"; + + public static UnRegRequestHeader buildHeader(Map headerParam) { + UnRegRequestHeader header = new UnRegRequestHeader(); + header.setCode(MapUtils.getString(headerParam, ProtocolKey.REQUEST_CODE)); + header.setVersion(ProtocolVersion.get(MapUtils.getString(headerParam, ProtocolKey.VERSION))); + String lan = StringUtils.isBlank(MapUtils.getString(headerParam, ProtocolKey.LANGUAGE)) + ? Constants.LANGUAGE_JAVA : MapUtils.getString(headerParam, ProtocolKey.LANGUAGE); + header.setLanguage(lan); + header.setEnv(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.ENV)); + header.setIdc(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IDC)); + header.setSys(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.SYS)); + header.setPid(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PID)); + header.setIp(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IP)); + header.setUsername(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.USERNAME)); + header.setPasswd(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PASSWD)); + return header; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public ProtocolVersion getVersion() { + return version; + } + + public void setVersion(ProtocolVersion version) { + this.version = version; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getIdc() { + return idc; + } + + public void setIdc(String idc) { + this.idc = idc; + } + + public String getSys() { + return sys; + } + + public void setSys(String sys) { + this.sys = sys; + } + + public String getPid() { + return pid; + } + + public void setPid(String pid) { + this.pid = pid; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPasswd() { + return passwd; + } + + public void setPasswd(String passwd) { + this.passwd = passwd; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.LANGUAGE, language); + map.put(ProtocolKey.VERSION, version); + map.put(ProtocolKey.ClientInstanceKey.ENV, env); + map.put(ProtocolKey.ClientInstanceKey.IDC, idc); + map.put(ProtocolKey.ClientInstanceKey.SYS, sys); + map.put(ProtocolKey.ClientInstanceKey.PID, pid); + map.put(ProtocolKey.ClientInstanceKey.IP, ip); + map.put(ProtocolKey.ClientInstanceKey.USERNAME, username); + map.put(ProtocolKey.ClientInstanceKey.PASSWD, passwd); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("unRegRequestHeader={") + .append("code=").append(code).append(",") + .append("language=").append(language).append(",") + .append("version=").append(version).append(",") + .append("env=").append(env).append(",") + .append("idc=").append(idc).append(",") + .append("sys=").append(sys).append(",") + .append("pid=").append(pid).append(",") + .append("ip=").append(ip).append(",") + .append("username=").append(username).append(",") + .append("passwd=").append(passwd).append("}"); + return sb.toString(); + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/UnRegResponseHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/UnRegResponseHeader.java new file mode 100644 index 0000000000..550e796be7 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/UnRegResponseHeader.java @@ -0,0 +1,113 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import java.util.HashMap; +import java.util.Map; + +public class UnRegResponseHeader extends Header { + + private int code; + + private String eventMeshCluster; + + private String eventMeshIp; + + private String eventMeshEnv; + + private String eventMeshIdc; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getEventMeshCluster() { + return eventMeshCluster; + } + + public void setEventMeshCluster(String eventMeshCluster) { + this.eventMeshCluster = eventMeshCluster; + } + + public String getEventMeshIp() { + return eventMeshIp; + } + + public void setEventMeshIp(String eventMeshIp) { + this.eventMeshIp = eventMeshIp; + } + + public String getEventMeshEnv() { + return eventMeshEnv; + } + + public void setEventMeshEnv(String eventMeshEnv) { + this.eventMeshEnv = eventMeshEnv; + } + + public String getEventMeshIdc() { + return eventMeshIdc; + } + + public void setEventMeshIdc(String eventMeshIdc) { + this.eventMeshIdc = eventMeshIdc; + } + + public static UnRegResponseHeader buildHeader(Integer requestCode, String eventMeshCluster, + String eventMeshIp, String eventMeshEnv, String eventMeshIDC) { + UnRegResponseHeader regResponseHeader = new UnRegResponseHeader(); + regResponseHeader.setCode(requestCode); + regResponseHeader.setEventMeshCluster(eventMeshCluster); + regResponseHeader.setEventMeshIp(eventMeshIp); + regResponseHeader.setEventMeshEnv(eventMeshEnv); + regResponseHeader.setEventMeshIdc(eventMeshIDC); + return regResponseHeader; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("nnRegResponseHeader={") + .append("code=").append(code).append(",") + .append("eventMeshEnv=").append(eventMeshEnv).append(",") + .append("eventMeshIdc=").append(eventMeshIdc).append(",") + .append("eventMeshCluster=").append(eventMeshCluster).append(",") + .append("eventMeshIp=").append(eventMeshIp).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER, eventMeshCluster); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP, eventMeshIp); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV, eventMeshEnv); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC, eventMeshIdc); + return map; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/UnSubscribeRequestHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/UnSubscribeRequestHeader.java new file mode 100644 index 0000000000..452e278846 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/UnSubscribeRequestHeader.java @@ -0,0 +1,182 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +public class UnSubscribeRequestHeader extends Header { + + private String code; + + private String language; + + private ProtocolVersion version; + + private String env; + + private String idc; + + private String sys; + + private String pid; + + private String ip; + + private String username; + + private String passwd; + + public static UnSubscribeRequestHeader buildHeader(Map headerParam) { + UnSubscribeRequestHeader header = new UnSubscribeRequestHeader(); + header.setCode(MapUtils.getString(headerParam, ProtocolKey.REQUEST_CODE)); + header.setVersion(ProtocolVersion.get(MapUtils.getString(headerParam, ProtocolKey.VERSION))); + String lan = StringUtils.isBlank(MapUtils.getString(headerParam, ProtocolKey.LANGUAGE)) + ? Constants.LANGUAGE_JAVA : MapUtils.getString(headerParam, ProtocolKey.LANGUAGE); + header.setLanguage(lan); + header.setEnv(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.ENV)); + header.setIdc(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IDC)); + header.setSys(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.SYS)); + header.setPid(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PID)); + header.setIp(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IP)); + header.setUsername(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.USERNAME)); + header.setPasswd(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PASSWD)); + return header; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public ProtocolVersion getVersion() { + return version; + } + + public void setVersion(ProtocolVersion version) { + this.version = version; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getIdc() { + return idc; + } + + public void setIdc(String idc) { + this.idc = idc; + } + + public String getSys() { + return sys; + } + + public void setSys(String sys) { + this.sys = sys; + } + + public String getPid() { + return pid; + } + + public void setPid(String pid) { + this.pid = pid; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPasswd() { + return passwd; + } + + public void setPasswd(String passwd) { + this.passwd = passwd; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.LANGUAGE, language); + map.put(ProtocolKey.VERSION, version); + map.put(ProtocolKey.ClientInstanceKey.ENV, env); + map.put(ProtocolKey.ClientInstanceKey.IDC, idc); + map.put(ProtocolKey.ClientInstanceKey.SYS, sys); + map.put(ProtocolKey.ClientInstanceKey.PID, pid); + map.put(ProtocolKey.ClientInstanceKey.IP, ip); + map.put(ProtocolKey.ClientInstanceKey.USERNAME, username); + map.put(ProtocolKey.ClientInstanceKey.PASSWD, passwd); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("subscribeRequestHeader={") + .append("code=").append(code).append(",") + .append("language=").append(language).append(",") + .append("version=").append(version).append(",") + .append("env=").append(env).append(",") + .append("idc=").append(idc).append(",") + .append("sys=").append(sys).append(",") + .append("pid=").append(pid).append(",") + .append("ip=").append(ip).append(",") + .append("username=").append(username).append(",") + .append("passwd=").append(passwd).append("}"); + return sb.toString(); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/UnSubscribeResponseHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/UnSubscribeResponseHeader.java new file mode 100644 index 0000000000..bb90b4bf75 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/client/UnSubscribeResponseHeader.java @@ -0,0 +1,111 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import java.util.HashMap; +import java.util.Map; + +public class UnSubscribeResponseHeader extends Header { + + private int code; + + private String eventMeshCluster; + + private String eventMeshIp; + + private String eventMeshEnv; + + private String eventMeshIdc; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getEventMeshCluster() { + return eventMeshCluster; + } + + public void setEventMeshCluster(String eventMeshCluster) { + this.eventMeshCluster = eventMeshCluster; + } + + public String getEventMeshIp() { + return eventMeshIp; + } + + public void setEventMeshIp(String eventMeshIp) { + this.eventMeshIp = eventMeshIp; + } + + public String getEventMeshEnv() { + return eventMeshEnv; + } + + public void setEventMeshEnv(String eventMeshEnv) { + this.eventMeshEnv = eventMeshEnv; + } + + public String getEventMeshIdc() { + return eventMeshIdc; + } + + public void setEventMeshIdc(String eventMeshIdc) { + this.eventMeshIdc = eventMeshIdc; + } + + public static UnSubscribeResponseHeader buildHeader(Integer requestCode, String eventMeshCluster, + String eventMeshIp, String eventMeshEnv, String eventMeshIDC) { + UnSubscribeResponseHeader unSubscribeResponseHeader = new UnSubscribeResponseHeader(); + unSubscribeResponseHeader.setCode(requestCode); + unSubscribeResponseHeader.setEventMeshCluster(eventMeshCluster); + unSubscribeResponseHeader.setEventMeshIp(eventMeshIp); + unSubscribeResponseHeader.setEventMeshEnv(eventMeshEnv); + unSubscribeResponseHeader.setEventMeshIdc(eventMeshIDC); + return unSubscribeResponseHeader; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("unSubscribeResponseHeader={") + .append("code=").append(code).append(",") + .append("eventMeshEnv=").append(eventMeshEnv).append(",") + .append("eventMeshIdc=").append(eventMeshIdc).append(",") + .append("eventMeshCluster=").append(eventMeshCluster).append(",") + .append("eventMeshIp=").append(eventMeshIp).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER, eventMeshCluster); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP, eventMeshIp); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV, eventMeshEnv); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC, eventMeshIdc); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/PushMessageRequestHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/PushMessageRequestHeader.java new file mode 100644 index 0000000000..726c08a720 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/PushMessageRequestHeader.java @@ -0,0 +1,145 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import org.apache.commons.collections4.MapUtils; + +import java.util.HashMap; +import java.util.Map; + +public class PushMessageRequestHeader extends Header { + + //request code + private int code; + + //requester language description + private String language; + + //protocol version adopted by requester, default:1.0 + private ProtocolVersion version; + + private String eventMeshCluster; + + private String eventMeshIp; + + private String eventMeshEnv; + + private String eventMeshIdc; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getEventMeshCluster() { + return eventMeshCluster; + } + + public void setEventMeshCluster(String eventMeshCluster) { + this.eventMeshCluster = eventMeshCluster; + } + + public String getEventMeshIp() { + return eventMeshIp; + } + + public void setEventMeshIp(String eventMeshIp) { + this.eventMeshIp = eventMeshIp; + } + + public String getEventMeshEnv() { + return eventMeshEnv; + } + + public void setEventMeshEnv(String eventMeshEnv) { + this.eventMeshEnv = eventMeshEnv; + } + + public String getEventMeshIdc() { + return eventMeshIdc; + } + + public void setEventMeshIdc(String eventMeshIdc) { + this.eventMeshIdc = eventMeshIdc; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public ProtocolVersion getVersion() { + return version; + } + + public void setVersion(ProtocolVersion version) { + this.version = version; + } + + public static PushMessageRequestHeader buildHeader(final Map headerParam) { + PushMessageRequestHeader pushMessageRequestHeader = new PushMessageRequestHeader(); + pushMessageRequestHeader.setCode(MapUtils.getIntValue(headerParam, ProtocolKey.REQUEST_CODE)); + pushMessageRequestHeader.setLanguage(MapUtils.getString(headerParam, ProtocolKey.LANGUAGE, Constants.LANGUAGE_JAVA)); + pushMessageRequestHeader.setVersion(ProtocolVersion.get(MapUtils.getString(headerParam, ProtocolKey.VERSION))); + pushMessageRequestHeader.setEventMeshCluster(MapUtils.getString(headerParam, ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER)); + pushMessageRequestHeader.setEventMeshIp(MapUtils.getString(headerParam, ProtocolKey.EventMeshInstanceKey.EVENTMESHIP)); + pushMessageRequestHeader.setEventMeshEnv(MapUtils.getString(headerParam, ProtocolKey.EventMeshInstanceKey.EVENTMESHENV)); + pushMessageRequestHeader.setEventMeshIdc(MapUtils.getString(headerParam, ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC)); + return pushMessageRequestHeader; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.LANGUAGE, language); + map.put(ProtocolKey.VERSION, version); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER, eventMeshCluster); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP, eventMeshIp); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV, eventMeshEnv); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC, eventMeshIdc); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("pushMessageRequestHeader={") + .append("code=").append(code).append(",") + .append("language=").append(language).append(",") + .append("version=").append(version.getVersion()).append(",") + .append("eventMeshEnv=").append(eventMeshEnv).append(",") + .append("eventMeshIdc=").append(eventMeshIdc).append(",") + .append("eventMeshCluster=").append(eventMeshCluster).append(",") + .append("eventMeshIp=").append(eventMeshIp).append("}"); + return sb.toString(); + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/PushMessageResponseHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/PushMessageResponseHeader.java new file mode 100644 index 0000000000..c5b727111d --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/PushMessageResponseHeader.java @@ -0,0 +1,187 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import java.util.HashMap; +import java.util.Map; + +public class PushMessageResponseHeader extends Header { + + //response code + private int code; + + //requester language description + private String language; + + //protocol version adopted by requester, default:1.0 + private ProtocolVersion version; + + //the environment number of the requester + private String env; + + //the IDC of the requester + private String idc; + + //subsystem of the requester + private String sys; + + //PID of the requester + private String pid; + + //IP of the requester + private String ip; + + //USERNAME of the requester + private String username; + + //PASSWD of the requester + private String passwd; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPasswd() { + return passwd; + } + + public void setPasswd(String passwd) { + this.passwd = passwd; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public ProtocolVersion getVersion() { + return version; + } + + public void setVersion(ProtocolVersion version) { + this.version = version; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getIdc() { + return idc; + } + + public void setIdc(String idc) { + this.idc = idc; + } + + public String getSys() { + return sys; + } + + public void setSys(String sys) { + this.sys = sys; + } + + public String getPid() { + return pid; + } + + public void setPid(String pid) { + this.pid = pid; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public static PushMessageResponseHeader buildHeader(int requestCode, String clientEnv, String clientIDC, + String clientSysId, String clientPid, String clientIP) { + PushMessageResponseHeader pushMessageResponseHeader = new PushMessageResponseHeader(); + pushMessageResponseHeader.setCode(requestCode); + pushMessageResponseHeader.setVersion(ProtocolVersion.V1); + pushMessageResponseHeader.setLanguage(Constants.LANGUAGE_JAVA); + pushMessageResponseHeader.setEnv(clientEnv); + pushMessageResponseHeader.setIdc(clientIDC); + pushMessageResponseHeader.setSys(clientSysId); + pushMessageResponseHeader.setPid(clientPid); + pushMessageResponseHeader.setIp(clientIP); + return pushMessageResponseHeader; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("pushMessageResponseHeader={") + .append("code=").append(code).append(",") + .append("language=").append(language).append(",") + .append("version=").append(version).append(",") + .append("env=").append(env).append(",") + .append("idc=").append(idc).append(",") + .append("sys=").append(sys).append(",") + .append("pid=").append(pid).append(",") + .append("ip=").append(ip).append(",") + .append("username=").append(username).append(",") + .append("passwd=").append(passwd).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.LANGUAGE, language); + map.put(ProtocolKey.VERSION, version); + map.put(ProtocolKey.ClientInstanceKey.ENV, env); + map.put(ProtocolKey.ClientInstanceKey.IDC, idc); + map.put(ProtocolKey.ClientInstanceKey.SYS, sys); + map.put(ProtocolKey.ClientInstanceKey.PID, pid); + map.put(ProtocolKey.ClientInstanceKey.IP, ip); + map.put(ProtocolKey.ClientInstanceKey.USERNAME, username); + map.put(ProtocolKey.ClientInstanceKey.PASSWD, passwd); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/ReplyMessageRequestHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/ReplyMessageRequestHeader.java new file mode 100644 index 0000000000..ad4a8ec24e --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/ReplyMessageRequestHeader.java @@ -0,0 +1,229 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +public class ReplyMessageRequestHeader extends Header { + + //request code + private String code; + + //requester language description + private String language; + + //protocol version adopted by requester, default:1.0 + private ProtocolVersion version; + + //protocol type, cloudevents or eventmeshMessage + private String protocolType; + + //protocol version, cloudevents:1.0 or 0.3 + private String protocolVersion; + + //protocol desc + private String protocolDesc; + + //the environment number of the requester + private String env; + + //the IDC of the requester + private String idc; + + //subsystem of the requester + private String sys; + + //PID of the requester + private String pid; + + //IP of the requester + private String ip; + + //USERNAME of the requester + private String username; + + //PASSWD of the requester + private String passwd; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPasswd() { + return passwd; + } + + public void setPasswd(String passwd) { + this.passwd = passwd; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public ProtocolVersion getVersion() { + return version; + } + + public void setVersion(ProtocolVersion version) { + this.version = version; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getIdc() { + return idc; + } + + public void setIdc(String idc) { + this.idc = idc; + } + + public String getSys() { + return sys; + } + + public void setSys(String sys) { + this.sys = sys; + } + + public String getPid() { + return pid; + } + + public void setPid(String pid) { + this.pid = pid; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getProtocolType() { + return protocolType; + } + + public void setProtocolType(String protocolType) { + this.protocolType = protocolType; + } + + public String getProtocolVersion() { + return protocolVersion; + } + + public void setProtocolVersion(String protocolVersion) { + this.protocolVersion = protocolVersion; + } + + public String getProtocolDesc() { + return protocolDesc; + } + + public void setProtocolDesc(String protocolDesc) { + this.protocolDesc = protocolDesc; + } + + public static ReplyMessageRequestHeader buildHeader(Map headerParam) { + ReplyMessageRequestHeader header = new ReplyMessageRequestHeader(); + header.setCode(MapUtils.getString(headerParam, ProtocolKey.REQUEST_CODE)); + header.setVersion(ProtocolVersion.get(MapUtils.getString(headerParam, ProtocolKey.VERSION))); + header.setProtocolType(MapUtils.getString(headerParam, ProtocolKey.PROTOCOL_TYPE)); + header.setProtocolVersion(MapUtils.getString(headerParam, ProtocolKey.PROTOCOL_VERSION)); + header.setProtocolDesc(MapUtils.getString(headerParam, ProtocolKey.PROTOCOL_DESC)); + String lan = StringUtils.isBlank(MapUtils.getString(headerParam, ProtocolKey.LANGUAGE)) + ? Constants.LANGUAGE_JAVA : MapUtils.getString(headerParam, ProtocolKey.LANGUAGE); + header.setLanguage(lan); + header.setEnv(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.ENV)); + header.setIdc(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IDC)); + header.setSys(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.SYS)); + header.setPid(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PID)); + header.setIp(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IP)); + header.setUsername(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.USERNAME)); + header.setPasswd(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PASSWD)); + return header; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.LANGUAGE, language); + map.put(ProtocolKey.VERSION, version); + map.put(ProtocolKey.ClientInstanceKey.ENV, env); + map.put(ProtocolKey.ClientInstanceKey.IDC, idc); + map.put(ProtocolKey.ClientInstanceKey.SYS, sys); + map.put(ProtocolKey.ClientInstanceKey.PID, pid); + map.put(ProtocolKey.ClientInstanceKey.IP, ip); + map.put(ProtocolKey.ClientInstanceKey.USERNAME, username); + map.put(ProtocolKey.ClientInstanceKey.PASSWD, passwd); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("replyMessageRequestHeader={") + .append("code=").append(code).append(",") + .append("language=").append(language).append(",") + .append("version=").append(version).append(",") + .append("env=").append(env).append(",") + .append("idc=").append(idc).append(",") + .append("sys=").append(sys).append(",") + .append("pid=").append(pid).append(",") + .append("ip=").append(ip).append(",") + .append("username=").append(username).append(",") + .append("passwd=").append(passwd).append("}"); + return sb.toString(); + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/ReplyMessageResponseHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/ReplyMessageResponseHeader.java new file mode 100644 index 0000000000..20d6f107e9 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/ReplyMessageResponseHeader.java @@ -0,0 +1,118 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import java.util.HashMap; +import java.util.Map; + +public class ReplyMessageResponseHeader extends Header { + + //response code, as same as the request code + private int code; + + //The cluster name of the EventMesh that processes the request + private String eventMeshCluster; + + //IP of the EventMesh that processes the request + private String eventMeshIp; + + //Environment number of the EventMesh that processes the request + private String eventMeshEnv; + + //IDC of the EventMesh that processes the request + private String eventMeshIdc; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getEventMeshCluster() { + return eventMeshCluster; + } + + public void setEventMeshCluster(String eventMeshCluster) { + this.eventMeshCluster = eventMeshCluster; + } + + public String getEventMeshIp() { + return eventMeshIp; + } + + public void setEventMeshIp(String eventMeshIp) { + this.eventMeshIp = eventMeshIp; + } + + public String getEventMeshEnv() { + return eventMeshEnv; + } + + public void setEventMeshEnv(String eventMeshEnv) { + this.eventMeshEnv = eventMeshEnv; + } + + public String getEventMeshIdc() { + return eventMeshIdc; + } + + public void setEventMeshIdc(String eventMeshIdc) { + this.eventMeshIdc = eventMeshIdc; + } + + public static ReplyMessageResponseHeader buildHeader(Integer requestCode, String eventMeshCluster, + String eventMeshIp, String eventMeshEnv, + String eventMeshIDC) { + ReplyMessageResponseHeader replyMessageResponseHeader = new ReplyMessageResponseHeader(); + replyMessageResponseHeader.setCode(requestCode); + replyMessageResponseHeader.setEventMeshCluster(eventMeshCluster); + replyMessageResponseHeader.setEventMeshIp(eventMeshIp); + replyMessageResponseHeader.setEventMeshEnv(eventMeshEnv); + replyMessageResponseHeader.setEventMeshIdc(eventMeshIDC); + return replyMessageResponseHeader; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("replyMessageResponseHeader={") + .append("code=").append(code).append(",") + .append("eventMeshEnv=").append(eventMeshEnv).append(",") + .append("eventMeshIdc=").append(eventMeshIdc).append(",") + .append("eventMeshCluster=").append(eventMeshCluster).append(",") + .append("eventMeshIp=").append(eventMeshIp).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER, eventMeshCluster); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP, eventMeshIp); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV, eventMeshEnv); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC, eventMeshIdc); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageBatchRequestHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageBatchRequestHeader.java new file mode 100644 index 0000000000..9ee63f71b2 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageBatchRequestHeader.java @@ -0,0 +1,230 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +public class SendMessageBatchRequestHeader extends Header { + + //request code + private String code; + + //requester language description + private String language; + + //protocol version adopted by requester, default:1.0 + private ProtocolVersion version; + + //protocol type, cloudevents or eventmeshMessage + private String protocolType; + + //protocol version, cloudevents:1.0 or 0.3 + private String protocolVersion; + + //protocol desc + private String protocolDesc; + + //the environment number of the requester + private String env; + + //the IDC of the requester + private String idc; + + //subsystem of the requester + private String sys; + + //PID of the requester + private String pid; + + //IP of the requester + private String ip; + + //USERNAME of the requester + private String username; + + //PASSWD of the requester + private String passwd; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPasswd() { + return passwd; + } + + public void setPasswd(String passwd) { + this.passwd = passwd; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public ProtocolVersion getVersion() { + return version; + } + + public void setVersion(ProtocolVersion version) { + this.version = version; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getIdc() { + return idc; + } + + public void setIdc(String idc) { + this.idc = idc; + } + + public String getSys() { + return sys; + } + + public void setSys(String sys) { + this.sys = sys; + } + + public String getPid() { + return pid; + } + + public void setPid(String pid) { + this.pid = pid; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getProtocolType() { + return protocolType; + } + + public void setProtocolType(String protocolType) { + this.protocolType = protocolType; + } + + public String getProtocolVersion() { + return protocolVersion; + } + + public void setProtocolVersion(String protocolVersion) { + this.protocolVersion = protocolVersion; + } + + public String getProtocolDesc() { + return protocolDesc; + } + + public void setProtocolDesc(String protocolDesc) { + this.protocolDesc = protocolDesc; + } + + public static SendMessageBatchRequestHeader buildHeader(final Map headerParam) { + SendMessageBatchRequestHeader header = new SendMessageBatchRequestHeader(); + header.setCode(MapUtils.getString(headerParam, ProtocolKey.REQUEST_CODE)); + header.setVersion(ProtocolVersion.get(MapUtils.getString(headerParam, ProtocolKey.VERSION))); + header.setProtocolType(MapUtils.getString(headerParam, ProtocolKey.PROTOCOL_TYPE)); + header.setProtocolVersion(MapUtils.getString(headerParam, ProtocolKey.PROTOCOL_VERSION)); + header.setProtocolDesc(MapUtils.getString(headerParam, ProtocolKey.PROTOCOL_DESC)); + String lan = StringUtils.isBlank(MapUtils.getString(headerParam, ProtocolKey.LANGUAGE)) + ? Constants.LANGUAGE_JAVA : MapUtils.getString(headerParam, ProtocolKey.LANGUAGE); + header.setLanguage(lan); + header.setEnv(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.ENV)); + header.setIdc(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IDC)); + header.setSys(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.SYS)); + header.setPid(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PID)); + header.setIp(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IP)); + header.setUsername(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.USERNAME)); + header.setPasswd(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PASSWD)); + return header; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.LANGUAGE, language); + map.put(ProtocolKey.VERSION, version); + map.put(ProtocolKey.ClientInstanceKey.ENV, env); + map.put(ProtocolKey.ClientInstanceKey.IDC, idc); + map.put(ProtocolKey.ClientInstanceKey.SYS, sys); + map.put(ProtocolKey.ClientInstanceKey.PID, pid); + map.put(ProtocolKey.ClientInstanceKey.IP, ip); + map.put(ProtocolKey.ClientInstanceKey.USERNAME, username); + map.put(ProtocolKey.ClientInstanceKey.PASSWD, passwd); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("sendMessageBatchRequestHeader={") + .append("code=").append(code).append(",") + .append("language=").append(language).append(",") + .append("version=").append(version).append(",") + .append("env=").append(env).append(",") + .append("idc=").append(idc).append(",") + .append("sys=").append(sys).append(",") + .append("pid=").append(pid).append(",") + .append("ip=").append(ip).append(",") + .append("username=").append(username).append(",") + .append("passwd=").append(passwd).append("}"); + return sb.toString(); + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageBatchResponseHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageBatchResponseHeader.java new file mode 100644 index 0000000000..4ddfde68b8 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageBatchResponseHeader.java @@ -0,0 +1,118 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import java.util.HashMap; +import java.util.Map; + +public class SendMessageBatchResponseHeader extends Header { + + //response code, as same as the request code + private int code; + + //The cluster name of the EventMesh that processes the request + private String eventMeshCluster; + + //IP of the EventMesh that processes the request + private String eventMeshIp; + + //Environment number of the EventMesh that processes the request + private String eventMeshEnv; + + //IDC of the EventMesh that processes the request + private String eventMeshIdc; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getEventMeshCluster() { + return eventMeshCluster; + } + + public void setEventMeshCluster(String eventMeshCluster) { + this.eventMeshCluster = eventMeshCluster; + } + + public String getEventMeshIp() { + return eventMeshIp; + } + + public void setEventMeshIp(String eventMeshIp) { + this.eventMeshIp = eventMeshIp; + } + + public String getEventMeshEnv() { + return eventMeshEnv; + } + + public void setEventMeshEnv(String eventMeshEnv) { + this.eventMeshEnv = eventMeshEnv; + } + + public String getEventMeshIdc() { + return eventMeshIdc; + } + + public void setEventMeshIdc(String eventMeshIdc) { + this.eventMeshIdc = eventMeshIdc; + } + + public static SendMessageBatchResponseHeader buildHeader(Integer requestCode, String eventMeshCluster, + String eventMeshIp, String eventMeshEnv, + String eventMeshIDC) { + SendMessageBatchResponseHeader sendMessageBatchResponseHeader = new SendMessageBatchResponseHeader(); + sendMessageBatchResponseHeader.setCode(requestCode); + sendMessageBatchResponseHeader.setEventMeshCluster(eventMeshCluster); + sendMessageBatchResponseHeader.setEventMeshEnv(eventMeshEnv); + sendMessageBatchResponseHeader.setEventMeshIdc(eventMeshIDC); + sendMessageBatchResponseHeader.setEventMeshIp(eventMeshIp); + return sendMessageBatchResponseHeader; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("sendMessageBatchResponseHeader={") + .append("code=").append(code).append(",") + .append("eventMeshEnv=").append(eventMeshEnv).append(",") + .append("eventMeshIdc=").append(eventMeshIdc).append(",") + .append("eventMeshCluster=").append(eventMeshCluster).append(",") + .append("eventMeshIp=").append(eventMeshIp).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER, eventMeshCluster); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP, eventMeshIp); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV, eventMeshEnv); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC, eventMeshIdc); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageBatchV2RequestHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageBatchV2RequestHeader.java new file mode 100644 index 0000000000..369d2c5460 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageBatchV2RequestHeader.java @@ -0,0 +1,229 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +public class SendMessageBatchV2RequestHeader extends Header { + + //request code + private String code; + + //requester language description + private String language; + + //protocol version adopted by requester, default:1.0 + private ProtocolVersion version; + + //protocol type, cloudevents or eventmeshMessage + private String protocolType; + + //protocol version, cloudevents:1.0 or 0.3 + private String protocolVersion; + + //protocol desc + private String protocolDesc; + + //the environment number of the requester + private String env; + + //the IDC of the requester + private String idc; + + //subsystem of the requester + private String sys; + + //PID of the requester + private String pid; + + //IP of the requester + private String ip; + + //USERNAME of the requester + private String username; + + //PASSWD of the requester + private String passwd; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPasswd() { + return passwd; + } + + public void setPasswd(String passwd) { + this.passwd = passwd; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public ProtocolVersion getVersion() { + return version; + } + + public void setVersion(ProtocolVersion version) { + this.version = version; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getIdc() { + return idc; + } + + public void setIdc(String idc) { + this.idc = idc; + } + + public String getSys() { + return sys; + } + + public void setSys(String sys) { + this.sys = sys; + } + + public String getPid() { + return pid; + } + + public void setPid(String pid) { + this.pid = pid; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getProtocolType() { + return protocolType; + } + + public void setProtocolType(String protocolType) { + this.protocolType = protocolType; + } + + public String getProtocolVersion() { + return protocolVersion; + } + + public void setProtocolVersion(String protocolVersion) { + this.protocolVersion = protocolVersion; + } + + public String getProtocolDesc() { + return protocolDesc; + } + + public void setProtocolDesc(String protocolDesc) { + this.protocolDesc = protocolDesc; + } + + public static SendMessageBatchV2RequestHeader buildHeader(final Map headerParam) { + SendMessageBatchV2RequestHeader header = new SendMessageBatchV2RequestHeader(); + header.setCode(MapUtils.getString(headerParam, ProtocolKey.REQUEST_CODE)); + header.setVersion(ProtocolVersion.get(MapUtils.getString(headerParam, ProtocolKey.VERSION))); + header.setProtocolType(MapUtils.getString(headerParam, ProtocolKey.PROTOCOL_TYPE)); + header.setProtocolVersion(MapUtils.getString(headerParam, ProtocolKey.PROTOCOL_VERSION)); + header.setProtocolDesc(MapUtils.getString(headerParam, ProtocolKey.PROTOCOL_DESC)); + + String lan = StringUtils.isBlank(MapUtils.getString(headerParam, ProtocolKey.LANGUAGE)) + ? Constants.LANGUAGE_JAVA : MapUtils.getString(headerParam, ProtocolKey.LANGUAGE); + header.setLanguage(lan); + header.setEnv(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.ENV)); + header.setIdc(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IDC)); + header.setSys(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.SYS)); + header.setPid(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PID)); + header.setIp(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IP)); + header.setUsername(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.USERNAME)); + header.setPasswd(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PASSWD)); + return header; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.LANGUAGE, language); + map.put(ProtocolKey.VERSION, version); + map.put(ProtocolKey.ClientInstanceKey.ENV, env); + map.put(ProtocolKey.ClientInstanceKey.IDC, idc); + map.put(ProtocolKey.ClientInstanceKey.SYS, sys); + map.put(ProtocolKey.ClientInstanceKey.PID, pid); + map.put(ProtocolKey.ClientInstanceKey.IP, ip); + map.put(ProtocolKey.ClientInstanceKey.USERNAME, username); + map.put(ProtocolKey.ClientInstanceKey.PASSWD, passwd); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("sendMessageBatchV2RequestHeader={") + .append("code=").append(code).append(",") + .append("language=").append(language).append(",") + .append("version=").append(version).append(",") + .append("env=").append(env).append(",") + .append("idc=").append(idc).append(",") + .append("sys=").append(sys).append(",") + .append("pid=").append(pid).append(",") + .append("ip=").append(ip).append(",") + .append("username=").append(username).append(",") + .append("passwd=").append(passwd).append("}"); + return sb.toString(); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageBatchV2ResponseHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageBatchV2ResponseHeader.java new file mode 100644 index 0000000000..e8d56f1514 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageBatchV2ResponseHeader.java @@ -0,0 +1,117 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.header.Header; +import org.apache.eventmesh.common.utils.IPUtils; + +import java.util.HashMap; +import java.util.Map; + +public class SendMessageBatchV2ResponseHeader extends Header { + + //response code, as same as the request code + private int code; + + //The cluster name of the EventMesh that processes the request + private String eventMeshCluster; + + //IP of the EventMesh that processes the request + private String eventMeshIp; + + //Environment number of the EventMesh that processes the request + private String eventMeshEnv; + + //IDC of the EventMesh that processes the request + private String eventMeshIdc; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getEventMeshCluster() { + return eventMeshCluster; + } + + public void setEventMeshCluster(String eventMeshCluster) { + this.eventMeshCluster = eventMeshCluster; + } + + public String getEventMeshIp() { + return eventMeshIp; + } + + public void setEventMeshIp(String eventMeshIp) { + this.eventMeshIp = eventMeshIp; + } + + public String getEventMeshEnv() { + return eventMeshEnv; + } + + public void setEventMeshEnv(String eventMeshEnv) { + this.eventMeshEnv = eventMeshEnv; + } + + public String getEventMeshIdc() { + return eventMeshIdc; + } + + public void setEventMeshIdc(String eventMeshIdc) { + this.eventMeshIdc = eventMeshIdc; + } + + public static SendMessageBatchV2ResponseHeader buildHeader(Integer requestCode, String eventMeshCluster, + String eventMeshEnv, String eventMeshIDC) { + SendMessageBatchV2ResponseHeader header = new SendMessageBatchV2ResponseHeader(); + header.setCode(requestCode); + header.setEventMeshCluster(eventMeshCluster); + header.setEventMeshEnv(eventMeshEnv); + header.setEventMeshIdc(eventMeshIDC); + header.setEventMeshIp(IPUtils.getLocalAddress()); + return header; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("sendMessageBatchV2ResponseHeader={") + .append("code=").append(code).append(",") + .append("eventMeshEnv=").append(eventMeshEnv).append(",") + .append("eventMeshIdc=").append(eventMeshIdc).append(",") + .append("eventMeshCluster=").append(eventMeshCluster).append(",") + .append("eventMeshIp=").append(eventMeshIp).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER, eventMeshCluster); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP, eventMeshIp); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV, eventMeshEnv); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC, eventMeshIdc); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageRequestHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageRequestHeader.java new file mode 100644 index 0000000000..19774280a4 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageRequestHeader.java @@ -0,0 +1,230 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +public class SendMessageRequestHeader extends Header { + + //request code + private String code; + + //requester language description + private String language; + + //protocol version adopted by requester, default:1.0 + private ProtocolVersion version; + + //protocol type, cloudevents or eventmeshMessage + private String protocolType; + + //protocol version, cloudevents:1.0 or 0.3 + private String protocolVersion; + + //protocol desc + private String protocolDesc; + + //the environment number of the requester + private String env; + + //the IDC of the requester + private String idc; + + //subsystem of the requester + private String sys; + + //PID of the requester + private String pid; + + //IP of the requester + private String ip; + + //USERNAME of the requester + private String username; + + //PASSWD of the requester + private String passwd; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPasswd() { + return passwd; + } + + public void setPasswd(String passwd) { + this.passwd = passwd; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public ProtocolVersion getVersion() { + return version; + } + + public void setVersion(ProtocolVersion version) { + this.version = version; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getIdc() { + return idc; + } + + public void setIdc(String idc) { + this.idc = idc; + } + + public String getSys() { + return sys; + } + + public void setSys(String sys) { + this.sys = sys; + } + + public String getPid() { + return pid; + } + + public void setPid(String pid) { + this.pid = pid; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getProtocolType() { + return protocolType; + } + + public void setProtocolType(String protocolType) { + this.protocolType = protocolType; + } + + public String getProtocolVersion() { + return protocolVersion; + } + + public void setProtocolVersion(String protocolVersion) { + this.protocolVersion = protocolVersion; + } + + public String getProtocolDesc() { + return protocolDesc; + } + + public void setProtocolDesc(String protocolDesc) { + this.protocolDesc = protocolDesc; + } + + public static SendMessageRequestHeader buildHeader(Map headerParam) { + SendMessageRequestHeader header = new SendMessageRequestHeader(); + header.setCode(MapUtils.getString(headerParam, ProtocolKey.REQUEST_CODE)); + header.setVersion(ProtocolVersion.get(MapUtils.getString(headerParam, ProtocolKey.VERSION))); + header.setProtocolType(MapUtils.getString(headerParam, ProtocolKey.PROTOCOL_TYPE)); + header.setProtocolVersion(MapUtils.getString(headerParam, ProtocolKey.PROTOCOL_VERSION)); + header.setProtocolDesc(MapUtils.getString(headerParam, ProtocolKey.PROTOCOL_DESC)); + + String lan = StringUtils.isBlank(MapUtils.getString(headerParam, ProtocolKey.LANGUAGE)) + ? Constants.LANGUAGE_JAVA : MapUtils.getString(headerParam, ProtocolKey.LANGUAGE); + header.setLanguage(lan); + header.setEnv(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.ENV)); + header.setIdc(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IDC)); + header.setSys(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.SYS)); + header.setPid(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PID)); + header.setIp(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.IP)); + header.setUsername(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.USERNAME)); + header.setPasswd(MapUtils.getString(headerParam, ProtocolKey.ClientInstanceKey.PASSWD)); + return header; + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.LANGUAGE, language); + map.put(ProtocolKey.VERSION, version); + map.put(ProtocolKey.ClientInstanceKey.ENV, env); + map.put(ProtocolKey.ClientInstanceKey.IDC, idc); + map.put(ProtocolKey.ClientInstanceKey.SYS, sys); + map.put(ProtocolKey.ClientInstanceKey.PID, pid); + map.put(ProtocolKey.ClientInstanceKey.IP, ip); + map.put(ProtocolKey.ClientInstanceKey.USERNAME, username); + map.put(ProtocolKey.ClientInstanceKey.PASSWD, passwd); + return map; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("sendMessageRequestHeader={") + .append("code=").append(code).append(",") + .append("language=").append(language).append(",") + .append("version=").append(version).append(",") + .append("env=").append(env).append(",") + .append("idc=").append(idc).append(",") + .append("sys=").append(sys).append(",") + .append("pid=").append(pid).append(",") + .append("ip=").append(ip).append(",") + .append("username=").append(username).append(",") + .append("passwd=").append(passwd).append("}"); + return sb.toString(); + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageResponseHeader.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageResponseHeader.java new file mode 100644 index 0000000000..a9db7ff587 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/http/header/message/SendMessageResponseHeader.java @@ -0,0 +1,118 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import java.util.HashMap; +import java.util.Map; + +public class SendMessageResponseHeader extends Header { + + //response code, as same as the request code + private int code; + + //The cluster name of the EventMesh that processes the request + private String eventMeshCluster; + + //IP of the EventMesh that processes the request + private String eventMeshIp; + + //Environment number of the EventMesh that processes the request + private String eventMeshEnv; + + //IDC of the EventMesh that processes the request + private String eventMeshIdc; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getEventMeshCluster() { + return eventMeshCluster; + } + + public void setEventMeshCluster(String eventMeshCluster) { + this.eventMeshCluster = eventMeshCluster; + } + + public String getEventMeshIp() { + return eventMeshIp; + } + + public void setEventMeshIp(String eventMeshIp) { + this.eventMeshIp = eventMeshIp; + } + + public String getEventMeshEnv() { + return eventMeshEnv; + } + + public void setEventMeshEnv(String eventMeshEnv) { + this.eventMeshEnv = eventMeshEnv; + } + + public String getEventMeshIdc() { + return eventMeshIdc; + } + + public void setEventMeshIdc(String eventMeshIdc) { + this.eventMeshIdc = eventMeshIdc; + } + + public static SendMessageResponseHeader buildHeader(Integer requestCode, String eventMeshCluster, + String eventMeshIp, String eventMeshEnv, + String eventMeshIDC) { + SendMessageResponseHeader sendMessageResponseHeader = new SendMessageResponseHeader(); + sendMessageResponseHeader.setCode(requestCode); + sendMessageResponseHeader.setEventMeshCluster(eventMeshCluster); + sendMessageResponseHeader.setEventMeshIp(eventMeshIp); + sendMessageResponseHeader.setEventMeshEnv(eventMeshEnv); + sendMessageResponseHeader.setEventMeshIdc(eventMeshIDC); + return sendMessageResponseHeader; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("sendMessageResponseHeader={") + .append("code=").append(code).append(",") + .append("eventMeshEnv=").append(eventMeshEnv).append(",") + .append("eventMeshIdc=").append(eventMeshIdc).append(",") + .append("eventMeshCluster=").append(eventMeshCluster).append(",") + .append("eventMeshIp=").append(eventMeshIp).append("}"); + return sb.toString(); + } + + @Override + public Map toMap() { + Map map = new HashMap(); + map.put(ProtocolKey.REQUEST_CODE, code); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER, eventMeshCluster); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP, eventMeshIp); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV, eventMeshEnv); + map.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC, eventMeshIdc); + return map; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Command.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Command.java new file mode 100644 index 0000000000..5e980a1b46 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Command.java @@ -0,0 +1,105 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.tcp; + +public enum Command { + + //heartbeat + HEARTBEAT_REQUEST(0), //client send heartbeat packet to server + HEARTBEAT_RESPONSE(1), //server response heartbeat packet of client + + //handshake + HELLO_REQUEST(2), //client send handshake request to server + HELLO_RESPONSE(3), //server response handshake request of client + + //disconnection + CLIENT_GOODBYE_REQUEST(4), //Notify server when client actively disconnects + CLIENT_GOODBYE_RESPONSE(5), //Server replies to client's active disconnection notification + SERVER_GOODBYE_REQUEST(6), //Notify client when server actively disconnects + SERVER_GOODBYE_RESPONSE(7), //Client replies to server's active disconnection notification + + //subscription management + SUBSCRIBE_REQUEST(8), //Subscription request sent by client to server + SUBSCRIBE_RESPONSE(9), //Server replies to client's subscription request + UNSUBSCRIBE_REQUEST(10), //Unsubscribe request from client to server + UNSUBSCRIBE_RESPONSE(11), //Server replies to client's unsubscribe request + + //monitor + LISTEN_REQUEST(12), //Request from client to server to start topic listening + LISTEN_RESPONSE(13), //The server replies to the client's listening request + + //RR + REQUEST_TO_SERVER(14), //The client sends the RR request to the server + REQUEST_TO_CLIENT(15), //The server pushes the RR request to the client + REQUEST_TO_CLIENT_ACK(16), //After receiving RR request, the client sends ACK to the server + RESPONSE_TO_SERVER(17), //The client sends the RR packet back to the server + RESPONSE_TO_CLIENT(18), //The server pushes the RR packet back to the client + RESPONSE_TO_CLIENT_ACK(19), //After receiving the return packet, the client sends ACK to the server + + //Asynchronous events + ASYNC_MESSAGE_TO_SERVER(20), //The client sends asynchronous events to the server + ASYNC_MESSAGE_TO_SERVER_ACK(21), //After receiving the asynchronous event, the server sends ack to the client + ASYNC_MESSAGE_TO_CLIENT(22), //The server pushes asynchronous events to the client + ASYNC_MESSAGE_TO_CLIENT_ACK(23), //After the client receives the asynchronous event, the ACK is sent to the server + + //radio broadcast + BROADCAST_MESSAGE_TO_SERVER(24), //The client sends the broadcast message to the server + BROADCAST_MESSAGE_TO_SERVER_ACK(25), //After receiving the broadcast message, the server sends ACK to the client + BROADCAST_MESSAGE_TO_CLIENT(26), //The server pushes the broadcast message to the client + BROADCAST_MESSAGE_TO_CLIENT_ACK(27), //After the client receives the broadcast message, the ACK is sent to the server + + //Log reporting + SYS_LOG_TO_LOGSERVER(28), //Business log reporting + + //RMB tracking log reporting + TRACE_LOG_TO_LOGSERVER(29), //RMB tracking log reporting + + //Redirecting instruction + REDIRECT_TO_CLIENT(30), //The server pushes the redirection instruction to the client + + //service register + REGISTER_REQUEST(31), //Client sends registration request to server + REGISTER_RESPONSE(32), //The server sends the registration result to the client + + //service unregister + UNREGISTER_REQUEST(33), //The client sends a de registration request to the server + UNREGISTER_RESPONSE(34), //The server will register the result to the client + + //The client asks which EventMesh to recommend + RECOMMEND_REQUEST(35), //Client sends recommendation request to server + RECOMMEND_RESPONSE(36); //The server will recommend the results to the client + + private final byte value; + + Command(int value) { + this.value = (byte) value; + } + + public byte getValue() { + return this.value; + } + + public static Command valueOf(int value) { + for (Command t : Command.values()) { + if (t.value == value) { + return t; + } + } + throw new IllegalArgumentException("No enum constant value=" + value); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/EventMeshMessage.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/EventMeshMessage.java new file mode 100644 index 0000000000..945824074c --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/EventMeshMessage.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.tcp; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class EventMeshMessage { + + private String topic; + private Map properties = new ConcurrentHashMap<>(); + private String body; +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Header.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Header.java new file mode 100644 index 0000000000..9c9a2890bc --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Header.java @@ -0,0 +1,79 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.tcp; + +import java.util.HashMap; +import java.util.Map; + +import lombok.Data; + +@Data +public class Header { + + private Command cmd; + private int code; + private String desc; + private String seq; + private Map properties = new HashMap<>(); + + public Header() { + } + + public Header(Command cmd, int code, String desc, String seq) { + this.cmd = cmd; + this.code = code; + this.desc = desc; + this.seq = seq; + } + + public Header(int code, String desc, String seq, Map properties) { + this.code = code; + this.desc = desc; + this.seq = seq; + this.properties = properties; + } + + + public void putProperty(final String name, final Object value) { + if (null == this.properties) { + this.properties = new HashMap<>(); + } + + this.properties.put(name, value); + } + + public Object getProperty(final String name) { + if (null == this.properties) { + return null; + } + return this.properties.get(name); + } + + public String getStringProperty(final String name) { + Object property = getProperty(name); + if (null == property) { + return null; + } + return property.toString(); + } + + public Command getCommand() { + return this.cmd; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/OPStatus.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/OPStatus.java new file mode 100644 index 0000000000..4ecfd04dbc --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/OPStatus.java @@ -0,0 +1,51 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.tcp; + +public enum OPStatus { + + SUCCESS(0, "success"), + FAIL(1, "fail"), + ACL_FAIL(2, "aclFail"), + TPS_OVERLOAD(3, "tpsOverload"); + + OPStatus(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + private Integer code; + + private String desc; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Package.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Package.java new file mode 100644 index 0000000000..a0c3d9d89f --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Package.java @@ -0,0 +1,59 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.tcp; + + +import org.apache.eventmesh.common.protocol.ProtocolTransportObject; + +public class Package implements ProtocolTransportObject { + + private static final long serialVersionUID = 3353018029137072737L; + private transient Header header; + private Object body; + + public Header getHeader() { + return header; + } + + public Object getBody() { + return body; + } + + + public void setHeader(Header header) { + this.header = header; + } + + public void setBody(Object body) { + this.body = body; + } + + public Package() { + + } + + public Package(Header header) { + this.header = header; + } + + public Package(Header header, Object body) { + this.header = header; + this.body = body; + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/RedirectInfo.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/RedirectInfo.java new file mode 100644 index 0000000000..8b552bfd20 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/RedirectInfo.java @@ -0,0 +1,56 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.tcp; + +public class RedirectInfo { + private String ip; + private int port; + + public RedirectInfo() { + } + + public RedirectInfo(String ip, int port) { + this.ip = ip; + this.port = port; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + @Override + public String toString() { + return "RedirectInfo{" + + "ip='" + ip + + '\'' + + ", port=" + port + + '}'; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Subscription.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Subscription.java new file mode 100644 index 0000000000..ad9f269417 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/Subscription.java @@ -0,0 +1,50 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.tcp; + +import org.apache.eventmesh.common.protocol.SubscriptionItem; + +import java.util.LinkedList; +import java.util.List; + +public class Subscription { + + private List topicList = new LinkedList<>(); + + public Subscription() { + } + + public Subscription(List topicList) { + this.topicList = topicList; + } + + public List getTopicList() { + return topicList; + } + + public void setTopicList(List topicList) { + this.topicList = topicList; + } + + @Override + public String toString() { + return "Subscription{" + + "topicList=" + topicList + + '}'; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/UserAgent.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/UserAgent.java new file mode 100644 index 0000000000..9e1d98b9b3 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/UserAgent.java @@ -0,0 +1,153 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.tcp; + +import java.util.Objects; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class UserAgent { + + private String env; + private String subsystem; + private String path; + private int pid; + private String host; + private int port; + private String version; + private String username; + private String password; + private String idc; + private String group; + private String purpose; + @Builder.Default + private int unack = 0; + + public UserAgent() { + } + + public UserAgent(String env, String subsystem, String path, int pid, String host, int port, String version, + String username, String password, String idc, String group, String purpose, int unack) { + this.env = env; + this.subsystem = subsystem; + this.path = path; + this.pid = pid; + this.host = host; + this.port = port; + this.version = version; + this.username = username; + this.password = password; + this.idc = idc; + this.group = group; + this.purpose = purpose; + this.unack = unack; + } + + @Override + public String toString() { + return String.format( + "UserAgent{env='%s', subsystem='%s', group='%s', path='%s', pid=%d, host='%s'," + + " port=%d, version='%s', idc='%s', purpose='%s', unack='%d'}", + env, subsystem, group, path, pid, host, port, version, idc, purpose, unack); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + UserAgent userAgent = (UserAgent) o; + + if (pid != userAgent.pid) { + return false; + } + + if (port != userAgent.port) { + return false; + } + + if (unack != userAgent.unack) { + return false; + } + + if (!Objects.equals(subsystem, userAgent.subsystem)) { + return false; + } + + if (!Objects.equals(group, userAgent.group)) { + return false; + } + + + if (!Objects.equals(path, userAgent.path)) { + return false; + } + + if (!Objects.equals(host, userAgent.host)) { + return false; + } + + if (!Objects.equals(purpose, userAgent.purpose)) { + return false; + } + + if (!Objects.equals(version, userAgent.version)) { + return false; + } + + if (!Objects.equals(username, userAgent.username)) { + return false; + } + + if (!Objects.equals(password, userAgent.password)) { + return false; + } + + if (!Objects.equals(env, userAgent.env)) { + return false; + } + + return Objects.equals(idc, userAgent.idc); + } + + @Override + public int hashCode() { + int result = subsystem != null ? subsystem.hashCode() : 0; + result = 31 * result + (group != null ? group.hashCode() : 0); + result = 31 * result + (path != null ? path.hashCode() : 0); + result = 31 * result + pid; + result = 31 * result + (host != null ? host.hashCode() : 0); + result = 31 * result + (purpose != null ? purpose.hashCode() : 0); + result = 31 * result + port; + result = 31 * result + (version != null ? version.hashCode() : 0); + result = 31 * result + (username != null ? username.hashCode() : 0); + result = 31 * result + (password != null ? password.hashCode() : 0); + result = 31 * result + (idc != null ? idc.hashCode() : 0); + result = 31 * result + (env != null ? env.hashCode() : 0); + result = 31 * result + unack; + return result; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/codec/Codec.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/codec/Codec.java new file mode 100644 index 0000000000..0db8587173 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/tcp/codec/Codec.java @@ -0,0 +1,245 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.tcp.codec; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.tcp.Command; +import org.apache.eventmesh.common.protocol.tcp.Header; +import org.apache.eventmesh.common.protocol.tcp.Package; +import org.apache.eventmesh.common.protocol.tcp.RedirectInfo; +import org.apache.eventmesh.common.protocol.tcp.Subscription; +import org.apache.eventmesh.common.protocol.tcp.UserAgent; +import org.apache.eventmesh.common.utils.JsonUtils; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.List; +import java.util.TimeZone; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; +import io.netty.handler.codec.ReplayingDecoder; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.google.common.base.Preconditions; + +public class Codec { + private static final Logger LOG = LoggerFactory.getLogger(Codec.class); + + private static final int FRAME_MAX_LENGTH = 1024 * 1024 * 4; + + private static final byte[] CONSTANT_MAGIC_FLAG = serializeBytes("EventMesh"); + private static final byte[] VERSION = serializeBytes("0000"); + + // todo: move to constants + public static final String CLOUD_EVENTS_PROTOCOL_NAME = "cloudevents"; + public static final String EM_MESSAGE_PROTOCOL_NAME = "eventmeshmessage"; + public static final String OPEN_MESSAGE_PROTOCOL_NAME = "openmessage"; + + // todo: use json util + private static ObjectMapper OBJECT_MAPPER; + + static { + OBJECT_MAPPER = new ObjectMapper(); + OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL); + OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + OBJECT_MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + OBJECT_MAPPER.setTimeZone(TimeZone.getDefault()); + } + + public static class Encoder extends MessageToByteEncoder { + @Override + public void encode(ChannelHandlerContext ctx, Package pkg, ByteBuf out) throws Exception { + Preconditions.checkNotNull(pkg, "TcpPackage cannot be null"); + final Header header = pkg.getHeader(); + Preconditions.checkNotNull(header, "TcpPackage header cannot be null", header); + if (LOG.isDebugEnabled()) { + LOG.debug("Encoder pkg={}", JsonUtils.serialize(pkg)); + } + + final byte[] headerData = serializeBytes(OBJECT_MAPPER.writeValueAsString(header)); + final byte[] bodyData; + + if (StringUtils.equals(CLOUD_EVENTS_PROTOCOL_NAME, header.getStringProperty(Constants.PROTOCOL_TYPE))) { + bodyData = (byte[]) pkg.getBody(); + } else { + bodyData = serializeBytes(OBJECT_MAPPER.writeValueAsString(pkg.getBody())); + } + + int headerLength = ArrayUtils.getLength(headerData); + int bodyLength = ArrayUtils.getLength(bodyData); + + int length = 4 + 4 + headerLength + bodyLength; + + if (length > FRAME_MAX_LENGTH) { + throw new IllegalArgumentException("message size is exceed limit!"); + } + + out.writeBytes(CONSTANT_MAGIC_FLAG); + out.writeBytes(VERSION); + out.writeInt(length); + out.writeInt(headerLength); + if (headerData != null) { + out.writeBytes(headerData); + } + if (bodyData != null) { + out.writeBytes(bodyData); + } + } + } + + public static class Decoder extends ReplayingDecoder { + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { + try { + if (null == in) { + return; + } + + byte[] flagBytes = parseFlag(in); + byte[] versionBytes = parseVersion(in); + validateFlag(flagBytes, versionBytes, ctx); + + final int length = in.readInt(); + final int headerLength = in.readInt(); + final int bodyLength = length - 8 - headerLength; + Header header = parseHeader(in, headerLength); + Object body = parseBody(in, header, bodyLength); + + Package pkg = new Package(header, body); + out.add(pkg); + } catch (Exception e) { + LOG.error(String.format("decode error| receive: %s.", deserializeBytes(in.array())), e); + throw e; + } + } + + private byte[] parseFlag(ByteBuf in) { + final byte[] flagBytes = new byte[CONSTANT_MAGIC_FLAG.length]; + in.readBytes(flagBytes); + return flagBytes; + } + + private byte[] parseVersion(ByteBuf in) { + final byte[] versionBytes = new byte[VERSION.length]; + in.readBytes(versionBytes); + return versionBytes; + } + + private Header parseHeader(ByteBuf in, int headerLength) throws JsonProcessingException { + if (headerLength <= 0) { + return null; + } + final byte[] headerData = new byte[headerLength]; + in.readBytes(headerData); + if (LOG.isDebugEnabled()) { + LOG.debug("Decode headerJson={}", deserializeBytes(headerData)); + } + return OBJECT_MAPPER.readValue(deserializeBytes(headerData), Header.class); + } + + private Object parseBody(ByteBuf in, Header header, int bodyLength) throws JsonProcessingException { + if (bodyLength <= 0 || header == null) { + return null; + } + final byte[] bodyData = new byte[bodyLength]; + in.readBytes(bodyData); + if (LOG.isDebugEnabled()) { + LOG.debug("Decode bodyJson={}", deserializeBytes(bodyData)); + } + return deserializeBody(deserializeBytes(bodyData), header); + } + + private void validateFlag(byte[] flagBytes, byte[] versionBytes, ChannelHandlerContext ctx) { + if (!Arrays.equals(flagBytes, CONSTANT_MAGIC_FLAG) || !Arrays.equals(versionBytes, VERSION)) { + String errorMsg = String.format("invalid magic flag or version|flag=%s|version=%s|remoteAddress=%s", + deserializeBytes(flagBytes), deserializeBytes(versionBytes), ctx.channel().remoteAddress()); + throw new IllegalArgumentException(errorMsg); + } + } + } + + private static Object deserializeBody(String bodyJsonString, Header header) throws JsonProcessingException { + Command command = header.getCmd(); + switch (command) { + case HELLO_REQUEST: + case RECOMMEND_REQUEST: + return OBJECT_MAPPER.readValue(bodyJsonString, UserAgent.class); + case SUBSCRIBE_REQUEST: + case UNSUBSCRIBE_REQUEST: + return OBJECT_MAPPER.readValue(bodyJsonString, Subscription.class); + case REQUEST_TO_SERVER: + case RESPONSE_TO_SERVER: + case ASYNC_MESSAGE_TO_SERVER: + case BROADCAST_MESSAGE_TO_SERVER: + case REQUEST_TO_CLIENT: + case RESPONSE_TO_CLIENT: + case ASYNC_MESSAGE_TO_CLIENT: + case BROADCAST_MESSAGE_TO_CLIENT: + case REQUEST_TO_CLIENT_ACK: + case RESPONSE_TO_CLIENT_ACK: + case ASYNC_MESSAGE_TO_CLIENT_ACK: + case BROADCAST_MESSAGE_TO_CLIENT_ACK: + // The message string will be deserialized by protocol plugin, if the event is cloudevents, the body is + // just a string. + return bodyJsonString; + case REDIRECT_TO_CLIENT: + return OBJECT_MAPPER.readValue(bodyJsonString, RedirectInfo.class); + default: + if (LOG.isWarnEnabled()) { + LOG.warn("Invalidate TCP command: {}", command); + } + return null; + } + } + + /** + * Deserialize bytes to String. + * + * @param bytes + * @return + */ + private static String deserializeBytes(byte[] bytes) { + return new String(bytes, Constants.DEFAULT_CHARSET); + } + + /** + * Serialize String to bytes. + * + * @param str + * @return + */ + private static byte[] serializeBytes(String str) { + if (str == null) { + return new byte[0]; + } + return str.getBytes(Constants.DEFAULT_CHARSET); + } + + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/EventmeshWorkflowGrpc.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/EventmeshWorkflowGrpc.java new file mode 100644 index 0000000000..3d25efdc43 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/EventmeshWorkflowGrpc.java @@ -0,0 +1,86 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: workflow.proto + +package org.apache.eventmesh.common.protocol.workflow.protos; + +@SuppressWarnings({"all"}) +public final class EventmeshWorkflowGrpc { + private EventmeshWorkflowGrpc() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_workflow_api_protocol_ExecuteRequest_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_workflow_api_protocol_ExecuteRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_eventmesh_workflow_api_protocol_ExecuteResponse_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_eventmesh_workflow_api_protocol_ExecuteResponse_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + String[] descriptorData = { + "\n\016workflow.proto\022\037eventmesh.workflow.api" + + ".protocol\"Z\n\016ExecuteRequest\022\n\n\002id\030\001 \001(\t\022" + + "\023\n\013instance_id\030\002 \001(\t\022\030\n\020task_instance_id" + + "\030\003 \001(\t\022\r\n\005input\030\004 \001(\t\"&\n\017ExecuteResponse" + + "\022\023\n\013instance_id\030\001 \001(\t2z\n\010Workflow\022n\n\007Exe" + + "cute\022/.eventmesh.workflow.api.protocol.E" + + "xecuteRequest\0320.eventmesh.workflow.api.p" + + "rotocol.ExecuteResponse\"\000B\226\001\n4org.apache" + + ".eventmesh.common.protocol.workflow.prot" + + "osB\025EventmeshWorkflowGrpcP\001ZEgithub.com/" + + "apache/incubator-eventmesh/eventmesh-wor" + + "kflow-go/api/protob\006proto3" + }; + descriptor = com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }); + internal_static_eventmesh_workflow_api_protocol_ExecuteRequest_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_eventmesh_workflow_api_protocol_ExecuteRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_workflow_api_protocol_ExecuteRequest_descriptor, + new String[] { "Id", "InstanceId", "TaskInstanceId", "Input", }); + internal_static_eventmesh_workflow_api_protocol_ExecuteResponse_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_eventmesh_workflow_api_protocol_ExecuteResponse_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_eventmesh_workflow_api_protocol_ExecuteResponse_descriptor, + new String[] { "InstanceId", }); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/ExecuteRequest.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/ExecuteRequest.java new file mode 100644 index 0000000000..e6d6418830 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/ExecuteRequest.java @@ -0,0 +1,988 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: workflow.proto + +package org.apache.eventmesh.common.protocol.workflow.protos; + +/** + * Protobuf type {@code eventmesh.workflow.api.protocol.ExecuteRequest} + */ +@SuppressWarnings({"all"}) +public final class ExecuteRequest extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:eventmesh.workflow.api.protocol.ExecuteRequest) + ExecuteRequestOrBuilder { +private static final long serialVersionUID = 0L; + // Use ExecuteRequest.newBuilder() to construct. + private ExecuteRequest(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private ExecuteRequest() { + id_ = ""; + instanceId_ = ""; + taskInstanceId_ = ""; + input_ = ""; + } + + @Override + @SuppressWarnings({"unused"}) + protected Object newInstance( + UnusedPrivateParameter unused) { + return new ExecuteRequest(); + } + + @Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private ExecuteRequest( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + String s = input.readStringRequireUtf8(); + + id_ = s; + break; + } + case 18: { + String s = input.readStringRequireUtf8(); + + instanceId_ = s; + break; + } + case 26: { + String s = input.readStringRequireUtf8(); + + taskInstanceId_ = s; + break; + } + case 34: { + String s = input.readStringRequireUtf8(); + + input_ = s; + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshWorkflowGrpc.internal_static_eventmesh_workflow_api_protocol_ExecuteRequest_descriptor; + } + + @Override + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshWorkflowGrpc.internal_static_eventmesh_workflow_api_protocol_ExecuteRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + ExecuteRequest.class, Builder.class); + } + + public static final int ID_FIELD_NUMBER = 1; + private volatile Object id_; + /** + * string id = 1; + * @return The id. + */ + @Override + public String getId() { + Object ref = id_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + id_ = s; + return s; + } + } + /** + * string id = 1; + * @return The bytes for id. + */ + @Override + public com.google.protobuf.ByteString + getIdBytes() { + Object ref = id_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int INSTANCE_ID_FIELD_NUMBER = 2; + private volatile Object instanceId_; + /** + * string instance_id = 2; + * @return The instanceId. + */ + @Override + public String getInstanceId() { + Object ref = instanceId_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + instanceId_ = s; + return s; + } + } + /** + * string instance_id = 2; + * @return The bytes for instanceId. + */ + @Override + public com.google.protobuf.ByteString + getInstanceIdBytes() { + Object ref = instanceId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + instanceId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TASK_INSTANCE_ID_FIELD_NUMBER = 3; + private volatile Object taskInstanceId_; + /** + * string task_instance_id = 3; + * @return The taskInstanceId. + */ + @Override + public String getTaskInstanceId() { + Object ref = taskInstanceId_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + taskInstanceId_ = s; + return s; + } + } + /** + * string task_instance_id = 3; + * @return The bytes for taskInstanceId. + */ + @Override + public com.google.protobuf.ByteString + getTaskInstanceIdBytes() { + Object ref = taskInstanceId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + taskInstanceId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int INPUT_FIELD_NUMBER = 4; + private volatile Object input_; + /** + * string input = 4; + * @return The input. + */ + @Override + public String getInput() { + Object ref = input_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + input_ = s; + return s; + } + } + /** + * string input = 4; + * @return The bytes for input. + */ + @Override + public com.google.protobuf.ByteString + getInputBytes() { + Object ref = input_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + input_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getIdBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, id_); + } + if (!getInstanceIdBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, instanceId_); + } + if (!getTaskInstanceIdBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, taskInstanceId_); + } + if (!getInputBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 4, input_); + } + unknownFields.writeTo(output); + } + + @Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getIdBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, id_); + } + if (!getInstanceIdBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, instanceId_); + } + if (!getTaskInstanceIdBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, taskInstanceId_); + } + if (!getInputBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, input_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof ExecuteRequest)) { + return super.equals(obj); + } + ExecuteRequest other = (ExecuteRequest) obj; + + if (!getId() + .equals(other.getId())) return false; + if (!getInstanceId() + .equals(other.getInstanceId())) return false; + if (!getTaskInstanceId() + .equals(other.getTaskInstanceId())) return false; + if (!getInput() + .equals(other.getInput())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId().hashCode(); + hash = (37 * hash) + INSTANCE_ID_FIELD_NUMBER; + hash = (53 * hash) + getInstanceId().hashCode(); + hash = (37 * hash) + TASK_INSTANCE_ID_FIELD_NUMBER; + hash = (53 * hash) + getTaskInstanceId().hashCode(); + hash = (37 * hash) + INPUT_FIELD_NUMBER; + hash = (53 * hash) + getInput().hashCode(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static ExecuteRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static ExecuteRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static ExecuteRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static ExecuteRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static ExecuteRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static ExecuteRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static ExecuteRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static ExecuteRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static ExecuteRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static ExecuteRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static ExecuteRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static ExecuteRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(ExecuteRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + return new Builder(parent); + } + /** + * Protobuf type {@code eventmesh.workflow.api.protocol.ExecuteRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:eventmesh.workflow.api.protocol.ExecuteRequest) + ExecuteRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return EventmeshWorkflowGrpc.internal_static_eventmesh_workflow_api_protocol_ExecuteRequest_descriptor; + } + + @Override + protected FieldAccessorTable + internalGetFieldAccessorTable() { + return EventmeshWorkflowGrpc.internal_static_eventmesh_workflow_api_protocol_ExecuteRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + ExecuteRequest.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.workflow.protos.ExecuteRequest.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @Override + public Builder clear() { + super.clear(); + id_ = ""; + + instanceId_ = ""; + + taskInstanceId_ = ""; + + input_ = ""; + + return this; + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return EventmeshWorkflowGrpc.internal_static_eventmesh_workflow_api_protocol_ExecuteRequest_descriptor; + } + + @Override + public ExecuteRequest getDefaultInstanceForType() { + return ExecuteRequest.getDefaultInstance(); + } + + @Override + public ExecuteRequest build() { + ExecuteRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @Override + public ExecuteRequest buildPartial() { + ExecuteRequest result = new ExecuteRequest(this); + result.id_ = id_; + result.instanceId_ = instanceId_; + result.taskInstanceId_ = taskInstanceId_; + result.input_ = input_; + onBuilt(); + return result; + } + + @Override + public Builder clone() { + return super.clone(); + } + @Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.setField(field, value); + } + @Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return super.setRepeatedField(field, index, value); + } + @Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.addRepeatedField(field, value); + } + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof ExecuteRequest) { + return mergeFrom((ExecuteRequest)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(ExecuteRequest other) { + if (other == ExecuteRequest.getDefaultInstance()) return this; + if (!other.getId().isEmpty()) { + id_ = other.id_; + onChanged(); + } + if (!other.getInstanceId().isEmpty()) { + instanceId_ = other.instanceId_; + onChanged(); + } + if (!other.getTaskInstanceId().isEmpty()) { + taskInstanceId_ = other.taskInstanceId_; + onChanged(); + } + if (!other.getInput().isEmpty()) { + input_ = other.input_; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + ExecuteRequest parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (ExecuteRequest) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private Object id_ = ""; + /** + * string id = 1; + * @return The id. + */ + public String getId() { + Object ref = id_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + id_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string id = 1; + * @return The bytes for id. + */ + public com.google.protobuf.ByteString + getIdBytes() { + Object ref = id_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string id = 1; + * @param value The id to set. + * @return This builder for chaining. + */ + public Builder setId( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + id_ = value; + onChanged(); + return this; + } + /** + * string id = 1; + * @return This builder for chaining. + */ + public Builder clearId() { + + id_ = getDefaultInstance().getId(); + onChanged(); + return this; + } + /** + * string id = 1; + * @param value The bytes for id to set. + * @return This builder for chaining. + */ + public Builder setIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + id_ = value; + onChanged(); + return this; + } + + private Object instanceId_ = ""; + /** + * string instance_id = 2; + * @return The instanceId. + */ + public String getInstanceId() { + Object ref = instanceId_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + instanceId_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string instance_id = 2; + * @return The bytes for instanceId. + */ + public com.google.protobuf.ByteString + getInstanceIdBytes() { + Object ref = instanceId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + instanceId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string instance_id = 2; + * @param value The instanceId to set. + * @return This builder for chaining. + */ + public Builder setInstanceId( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + instanceId_ = value; + onChanged(); + return this; + } + /** + * string instance_id = 2; + * @return This builder for chaining. + */ + public Builder clearInstanceId() { + + instanceId_ = getDefaultInstance().getInstanceId(); + onChanged(); + return this; + } + /** + * string instance_id = 2; + * @param value The bytes for instanceId to set. + * @return This builder for chaining. + */ + public Builder setInstanceIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + instanceId_ = value; + onChanged(); + return this; + } + + private Object taskInstanceId_ = ""; + /** + * string task_instance_id = 3; + * @return The taskInstanceId. + */ + public String getTaskInstanceId() { + Object ref = taskInstanceId_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + taskInstanceId_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string task_instance_id = 3; + * @return The bytes for taskInstanceId. + */ + public com.google.protobuf.ByteString + getTaskInstanceIdBytes() { + Object ref = taskInstanceId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + taskInstanceId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string task_instance_id = 3; + * @param value The taskInstanceId to set. + * @return This builder for chaining. + */ + public Builder setTaskInstanceId( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + taskInstanceId_ = value; + onChanged(); + return this; + } + /** + * string task_instance_id = 3; + * @return This builder for chaining. + */ + public Builder clearTaskInstanceId() { + + taskInstanceId_ = getDefaultInstance().getTaskInstanceId(); + onChanged(); + return this; + } + /** + * string task_instance_id = 3; + * @param value The bytes for taskInstanceId to set. + * @return This builder for chaining. + */ + public Builder setTaskInstanceIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + taskInstanceId_ = value; + onChanged(); + return this; + } + + private Object input_ = ""; + /** + * string input = 4; + * @return The input. + */ + public String getInput() { + Object ref = input_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + input_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string input = 4; + * @return The bytes for input. + */ + public com.google.protobuf.ByteString + getInputBytes() { + Object ref = input_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + input_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string input = 4; + * @param value The input to set. + * @return This builder for chaining. + */ + public Builder setInput( + String value) { + if (value == null) { + throw new NullPointerException(); + } + + input_ = value; + onChanged(); + return this; + } + /** + * string input = 4; + * @return This builder for chaining. + */ + public Builder clearInput() { + + input_ = getDefaultInstance().getInput(); + onChanged(); + return this; + } + /** + * string input = 4; + * @param value The bytes for input to set. + * @return This builder for chaining. + */ + public Builder setInputBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + input_ = value; + onChanged(); + return this; + } + @Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.workflow.api.protocol.ExecuteRequest) + } + + // @@protoc_insertion_point(class_scope:eventmesh.workflow.api.protocol.ExecuteRequest) + private static final ExecuteRequest DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new ExecuteRequest(); + } + + public static ExecuteRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @Override + public ExecuteRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new ExecuteRequest(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @Override + public ExecuteRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/ExecuteRequestOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/ExecuteRequestOrBuilder.java new file mode 100644 index 0000000000..2a6c536268 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/ExecuteRequestOrBuilder.java @@ -0,0 +1,75 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: workflow.proto + +package org.apache.eventmesh.common.protocol.workflow.protos; + +@SuppressWarnings({"all"}) +public interface ExecuteRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.workflow.api.protocol.ExecuteRequest) + com.google.protobuf.MessageOrBuilder { + + /** + * string id = 1; + * @return The id. + */ + String getId(); + /** + * string id = 1; + * @return The bytes for id. + */ + com.google.protobuf.ByteString + getIdBytes(); + + /** + * string instance_id = 2; + * @return The instanceId. + */ + String getInstanceId(); + /** + * string instance_id = 2; + * @return The bytes for instanceId. + */ + com.google.protobuf.ByteString + getInstanceIdBytes(); + + /** + * string task_instance_id = 3; + * @return The taskInstanceId. + */ + String getTaskInstanceId(); + /** + * string task_instance_id = 3; + * @return The bytes for taskInstanceId. + */ + com.google.protobuf.ByteString + getTaskInstanceIdBytes(); + + /** + * string input = 4; + * @return The input. + */ + String getInput(); + /** + * string input = 4; + * @return The bytes for input. + */ + com.google.protobuf.ByteString + getInputBytes(); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/ExecuteResponse.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/ExecuteResponse.java new file mode 100644 index 0000000000..c141b684d6 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/ExecuteResponse.java @@ -0,0 +1,576 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: workflow.proto + +package org.apache.eventmesh.common.protocol.workflow.protos; + +import java.util.Objects; + +import com.google.protobuf.ByteString; + +/** + * Protobuf type {@code eventmesh.workflow.api.protocol.ExecuteResponse} + */ +@SuppressWarnings({"all"}) +public final class ExecuteResponse extends com.google.protobuf.GeneratedMessageV3 implements ExecuteResponseOrBuilder { + + private static final long serialVersionUID = -6807939196493979674L; + + public static final int INSTANCE_ID_FIELD_NUMBER = 1; + private volatile String instanceId; + + private byte memoizedIsInitialized = -1; + + // Use ExecuteResponse.newBuilder() to construct. + private ExecuteResponse(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private ExecuteResponse() { + instanceId = ""; + } + + @Override + @SuppressWarnings({"unused"}) + protected Object newInstance(UnusedPrivateParameter unused) { + return new ExecuteResponse(); + } + + @Override + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { + return this.unknownFields; + } + + private ExecuteResponse( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + Objects.requireNonNull(extensionRegistry, "ExtensionRegistryLite can not be null"); + Objects.requireNonNull(input, "CodedInputStream can not be null"); + + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + instanceId = input.readStringRequireUtf8(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return EventmeshWorkflowGrpc.internal_static_eventmesh_workflow_api_protocol_ExecuteResponse_descriptor; + } + + @Override + protected FieldAccessorTable internalGetFieldAccessorTable() { + return EventmeshWorkflowGrpc.internal_static_eventmesh_workflow_api_protocol_ExecuteResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized(ExecuteResponse.class, Builder.class); + } + + + /** + * string instance_id = 1; + * + * @return The instanceId. + */ + @Override + public String getInstanceId() { + return instanceId; + } + + /** + * string instance_id = 1; + * + * @return The bytes for instanceId. + */ + @Override + public com.google.protobuf.ByteString getInstanceIdBytes() { + return ByteString.copyFromUtf8(instanceId); + } + + + @Override + public final boolean isInitialized() { + if (memoizedIsInitialized == 1) { + return true; + } + + if (memoizedIsInitialized == 0) { + return false; + } + + memoizedIsInitialized = 1; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (!getInstanceIdBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, instanceId); + } + unknownFields.writeTo(output); + } + + @Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getInstanceIdBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, instanceId); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof ExecuteResponse)) { + return super.equals(obj); + } + ExecuteResponse other = (ExecuteResponse) obj; + + if (!getInstanceId() + .equals(other.getInstanceId())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + INSTANCE_ID_FIELD_NUMBER; + hash = (53 * hash) + getInstanceId().hashCode(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static ExecuteResponse parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static ExecuteResponse parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static ExecuteResponse parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static ExecuteResponse parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static ExecuteResponse parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static ExecuteResponse parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static ExecuteResponse parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static ExecuteResponse parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static ExecuteResponse parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + + public static ExecuteResponse parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static ExecuteResponse parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + + public static ExecuteResponse parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @Override + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(ExecuteResponse prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + @Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + BuilderParent parent) { + return new Builder(parent); + } + + /** + * Protobuf type {@code eventmesh.workflow.api.protocol.ExecuteResponse} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + ExecuteResponseOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return EventmeshWorkflowGrpc.internal_static_eventmesh_workflow_api_protocol_ExecuteResponse_descriptor; + } + + @Override + protected FieldAccessorTable internalGetFieldAccessorTable() { + return EventmeshWorkflowGrpc.internal_static_eventmesh_workflow_api_protocol_ExecuteResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + ExecuteResponse.class, Builder.class); + } + + // Construct using org.apache.eventmesh.common.protocol.workflow.protos.ExecuteResponse.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder(BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) { + } + } + + @Override + public Builder clear() { + super.clear(); + instanceId = ""; + return this; + } + + @Override + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return EventmeshWorkflowGrpc.internal_static_eventmesh_workflow_api_protocol_ExecuteResponse_descriptor; + } + + @Override + public ExecuteResponse getDefaultInstanceForType() { + return ExecuteResponse.getDefaultInstance(); + } + + @Override + public ExecuteResponse build() { + ExecuteResponse result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @Override + public ExecuteResponse buildPartial() { + ExecuteResponse result = new ExecuteResponse(this); + result.instanceId = instanceId; + onBuilt(); + return result; + } + + @Override + public Builder clone() { + return super.clone(); + } + + @Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.setField(field, value); + } + + @Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + + @Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + + @Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, Object value) { + return super.setRepeatedField(field, index, value); + } + + @Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + Object value) { + return super.addRepeatedField(field, value); + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + Objects.requireNonNull(other, "Message can not be null"); + + if (other instanceof ExecuteResponse) { + return mergeFrom((ExecuteResponse) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(ExecuteResponse other) { + Objects.requireNonNull(other, "ExecuteResponse can not be null"); + + if (other == ExecuteResponse.getDefaultInstance()) return this; + if (!other.getInstanceId().isEmpty()) { + instanceId = other.instanceId; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Objects.requireNonNull(input, "CodedInputStream can not be null"); + Objects.requireNonNull(extensionRegistry, "ExtensionRegistryLite can not be null"); + + ExecuteResponse parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (ExecuteResponse) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + + return this; + } + + private String instanceId = ""; + + /** + * string instance_id = 1; + * + * @return The instanceId. + */ + public String getInstanceId() { + return instanceId; + } + + /** + * string instance_id = 1; + * + * @return The bytes for instanceId. + */ + public com.google.protobuf.ByteString getInstanceIdBytes() { + return ByteString.copyFromUtf8(instanceId); + } + + /** + * string instance_id = 1; + * + * @param value The instanceId to set. + * @return This builder for chaining. + */ + public Builder setInstanceId( + String value) { + Objects.requireNonNull(value, "InstanceId can not be null"); + instanceId = value; + onChanged(); + return this; + } + + /** + * string instance_id = 1; + * + * @return This builder for chaining. + */ + public Builder clearInstanceId() { + instanceId = getDefaultInstance().getInstanceId(); + onChanged(); + return this; + } + + /** + * string instance_id = 1; + * + * @param value The bytes for instanceId to set. + * @return This builder for chaining. + */ + public Builder setInstanceIdBytes( + com.google.protobuf.ByteString value) { + Objects.requireNonNull(value, "ByteString can not be null"); + checkByteStringIsUtf8(value); + instanceId = value.toStringUtf8(); + onChanged(); + return this; + } + + @Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:eventmesh.workflow.api.protocol.ExecuteResponse) + } + + // @@protoc_insertion_point(class_scope:eventmesh.workflow.api.protocol.ExecuteResponse) + private static final ExecuteResponse DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new ExecuteResponse(); + } + + public static ExecuteResponse getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @Override + public ExecuteResponse parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new ExecuteResponse(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @Override + public ExecuteResponse getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/ExecuteResponseOrBuilder.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/ExecuteResponseOrBuilder.java new file mode 100644 index 0000000000..160c32e648 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/ExecuteResponseOrBuilder.java @@ -0,0 +1,39 @@ +/* + * 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. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: workflow.proto + +package org.apache.eventmesh.common.protocol.workflow.protos; + +@SuppressWarnings({"all"}) +public interface ExecuteResponseOrBuilder extends + // @@protoc_insertion_point(interface_extends:eventmesh.workflow.api.protocol.ExecuteResponse) + com.google.protobuf.MessageOrBuilder { + + /** + * string instance_id = 1; + * @return The instanceId. + */ + String getInstanceId(); + /** + * string instance_id = 1; + * @return The bytes for instanceId. + */ + com.google.protobuf.ByteString + getInstanceIdBytes(); +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/WorkflowGrpc.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/WorkflowGrpc.java new file mode 100644 index 0000000000..c7bbffb074 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/protocol/workflow/protos/WorkflowGrpc.java @@ -0,0 +1,294 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.workflow.protos; + +import static io.grpc.MethodDescriptor.generateFullMethodName; + +/** + */ +@javax.annotation.Generated( + value = "by gRPC proto compiler (version 1.49.1-SNAPSHOT)", + comments = "Source: workflow.proto") +@io.grpc.stub.annotations.GrpcGenerated +@SuppressWarnings({"all"}) +public final class WorkflowGrpc { + + private WorkflowGrpc() {} + + public static final String SERVICE_NAME = "eventmesh.workflow.api.protocol.Workflow"; + + // Static method descriptors that strictly reflect the proto. + private static volatile io.grpc.MethodDescriptor getExecuteMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "Execute", + requestType = ExecuteRequest.class, + responseType = ExecuteResponse.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getExecuteMethod() { + io.grpc.MethodDescriptor getExecuteMethod; + if ((getExecuteMethod = WorkflowGrpc.getExecuteMethod) == null) { + synchronized (WorkflowGrpc.class) { + if ((getExecuteMethod = WorkflowGrpc.getExecuteMethod) == null) { + WorkflowGrpc.getExecuteMethod = getExecuteMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "Execute")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + ExecuteRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + ExecuteResponse.getDefaultInstance())) + .setSchemaDescriptor(new WorkflowMethodDescriptorSupplier("Execute")) + .build(); + } + } + } + return getExecuteMethod; + } + + /** + * Creates a new async stub that supports all call types for the service + */ + public static WorkflowStub newStub(io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @Override + public WorkflowStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new WorkflowStub(channel, callOptions); + } + }; + return WorkflowStub.newStub(factory, channel); + } + + /** + * Creates a new blocking-style stub that supports unary and streaming output calls on the service + */ + public static WorkflowBlockingStub newBlockingStub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @Override + public WorkflowBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new WorkflowBlockingStub(channel, callOptions); + } + }; + return WorkflowBlockingStub.newStub(factory, channel); + } + + /** + * Creates a new ListenableFuture-style stub that supports unary calls on the service + */ + public static WorkflowFutureStub newFutureStub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @Override + public WorkflowFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new WorkflowFutureStub(channel, callOptions); + } + }; + return WorkflowFutureStub.newStub(factory, channel); + } + + /** + */ + public static abstract class WorkflowImplBase implements io.grpc.BindableService { + + /** + */ + public void execute(ExecuteRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getExecuteMethod(), responseObserver); + } + + @Override public final io.grpc.ServerServiceDefinition bindService() { + return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) + .addMethod( + getExecuteMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + ExecuteRequest, + ExecuteResponse>( + this, METHODID_EXECUTE))) + .build(); + } + } + + /** + */ + public static final class WorkflowStub extends io.grpc.stub.AbstractAsyncStub { + private WorkflowStub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected WorkflowStub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new WorkflowStub(channel, callOptions); + } + + /** + */ + public void execute(ExecuteRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getExecuteMethod(), getCallOptions()), request, responseObserver); + } + } + + /** + */ + public static final class WorkflowBlockingStub extends io.grpc.stub.AbstractBlockingStub { + private WorkflowBlockingStub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected WorkflowBlockingStub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new WorkflowBlockingStub(channel, callOptions); + } + + /** + */ + public ExecuteResponse execute(ExecuteRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getExecuteMethod(), getCallOptions(), request); + } + } + + /** + */ + public static final class WorkflowFutureStub extends io.grpc.stub.AbstractFutureStub { + private WorkflowFutureStub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @Override + protected WorkflowFutureStub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new WorkflowFutureStub(channel, callOptions); + } + + /** + */ + public com.google.common.util.concurrent.ListenableFuture execute( + ExecuteRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getExecuteMethod(), getCallOptions()), request); + } + } + + private static final int METHODID_EXECUTE = 0; + + private static final class MethodHandlers implements + io.grpc.stub.ServerCalls.UnaryMethod, + io.grpc.stub.ServerCalls.ServerStreamingMethod, + io.grpc.stub.ServerCalls.ClientStreamingMethod, + io.grpc.stub.ServerCalls.BidiStreamingMethod { + private final WorkflowImplBase serviceImpl; + private final int methodId; + + MethodHandlers(WorkflowImplBase serviceImpl, int methodId) { + this.serviceImpl = serviceImpl; + this.methodId = methodId; + } + + @Override + @SuppressWarnings("unchecked") + public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + case METHODID_EXECUTE: + serviceImpl.execute((ExecuteRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + default: + throw new AssertionError(); + } + } + + @Override + @SuppressWarnings("unchecked") + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + default: + throw new AssertionError(); + } + } + } + + private static abstract class WorkflowBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier { + WorkflowBaseDescriptorSupplier() {} + + @Override + public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { + return EventmeshWorkflowGrpc.getDescriptor(); + } + + @Override + public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() { + return getFileDescriptor().findServiceByName("Workflow"); + } + } + + private static final class WorkflowFileDescriptorSupplier + extends WorkflowBaseDescriptorSupplier { + WorkflowFileDescriptorSupplier() {} + } + + private static final class WorkflowMethodDescriptorSupplier + extends WorkflowBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoMethodDescriptorSupplier { + private final String methodName; + + WorkflowMethodDescriptorSupplier(String methodName) { + this.methodName = methodName; + } + + @Override + public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() { + return getServiceDescriptor().findMethodByName(methodName); + } + } + + private static volatile io.grpc.ServiceDescriptor serviceDescriptor; + + public static io.grpc.ServiceDescriptor getServiceDescriptor() { + io.grpc.ServiceDescriptor result = serviceDescriptor; + if (result == null) { + synchronized (WorkflowGrpc.class) { + result = serviceDescriptor; + if (result == null) { + serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) + .setSchemaDescriptor(new WorkflowFileDescriptorSupplier()) + .addMethod(getExecuteMethod()) + .build(); + } + } + } + return result; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/AssertUtils.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/AssertUtils.java new file mode 100644 index 0000000000..0ba8745923 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/AssertUtils.java @@ -0,0 +1,61 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.utils; + +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +/** + * Assert + */ +public final class AssertUtils { + + /** + * assert obj not null + * + * @param obj obj + * @param message error message + */ + public static void notNull(final Object obj, final String message) { + isTrue(Objects.nonNull(obj), message); + } + + /** + * assert test is true + * + * @param test test + * @param message error message + */ + public static void isTrue(final Boolean test, final String message) { + if (!Boolean.TRUE.equals(test)) { + throw new IllegalArgumentException(message); + } + } + + /** + * assert str is not black + * @param str str + * @param message message + */ + public static void notBlack(final String str, final String message) { + isTrue(StringUtils.isNoneBlank(str), message); + } + + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/ConfigurationContextUtil.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/ConfigurationContextUtil.java new file mode 100644 index 0000000000..a7535f70ba --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/ConfigurationContextUtil.java @@ -0,0 +1,72 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.utils; + +import org.apache.eventmesh.common.config.CommonConfiguration; + +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +import com.google.common.collect.Lists; + +/** + * ConfigurationContextUtil. + */ +public class ConfigurationContextUtil { + + private static final ConcurrentHashMap CONFIGURATION_MAP = new ConcurrentHashMap<>(); + + public static final String HTTP = "HTTP"; + public static final String TCP = "TCP"; + public static final String GRPC = "GRPC"; + + public static final List KEYS = Lists.newArrayList(HTTP, TCP, GRPC); + + + /** + * Save http, tcp, grpc configuration at startup for global use. + * + * @param key + * @param configuration + */ + public static void putIfAbsent(String key, CommonConfiguration configuration) { + if (Objects.isNull(configuration)) { + return; + } + CONFIGURATION_MAP.putIfAbsent(key, configuration); + } + + /** + * Get the configuration of the specified key mapping. + * + * @param key + * @return configuration of the specified key mapping + */ + public static CommonConfiguration get(String key) { + return CONFIGURATION_MAP.get(key); + } + + + /** + * Removes all of the mappings from this map. + */ + public static void clear() { + CONFIGURATION_MAP.clear(); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/IPUtils.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/IPUtils.java new file mode 100644 index 0000000000..4976655be8 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/IPUtils.java @@ -0,0 +1,236 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.utils; + +import org.apache.commons.lang3.StringUtils; + +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.NetworkInterface; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.channel.Channel; + +import inet.ipaddr.HostName; +import inet.ipaddr.IPAddress; +import inet.ipaddr.IPAddressString; + +public class IPUtils { + + private static final Logger LOG = LoggerFactory.getLogger(IPUtils.class); + + public static String getLocalAddress() { + // if the progress works under docker environment + // return the host ip about this docker located from environment value + String dockerHostIp = System.getenv("docker_host_ip"); + if (dockerHostIp != null && !"".equals(dockerHostIp)) { + return dockerHostIp; + } + + //priority of networkInterface when generating client ip + String priority = System.getProperty("networkInterface.priority", "eth0 list = Arrays.asList(priority.split("<")); + ArrayList preferList = new ArrayList<>(list); + NetworkInterface preferNetworkInterface = null; + + try { + Enumeration enumeration1 = NetworkInterface.getNetworkInterfaces(); + while (enumeration1.hasMoreElements()) { + final NetworkInterface networkInterface = enumeration1.nextElement(); + if (preferNetworkInterface == null) { + preferNetworkInterface = networkInterface; + } else if (preferList.indexOf(networkInterface.getName()) //get the networkInterface that has higher priority + > preferList.indexOf(preferNetworkInterface.getName())) { + preferNetworkInterface = networkInterface; + } + } + + // Traversal Network interface to get the first non-loopback and non-private address + ArrayList ipv4Result = new ArrayList(); + ArrayList ipv6Result = new ArrayList(); + + if (preferNetworkInterface != null) { + final Enumeration en = preferNetworkInterface.getInetAddresses(); + getIpResult(ipv4Result, ipv6Result, en); + } else { + Enumeration enumeration = NetworkInterface.getNetworkInterfaces(); + while (enumeration.hasMoreElements()) { + final NetworkInterface networkInterface = enumeration.nextElement(); + final Enumeration en = networkInterface.getInetAddresses(); + getIpResult(ipv4Result, ipv6Result, en); + } + } + + // prefer ipv4 + if (!ipv4Result.isEmpty()) { + for (String ip : ipv4Result) { + if (isValidIPV4Address(ip) && !ip.startsWith("127.0") && !ip.startsWith("192.168")) { + return ip; + } + } + + return ipv4Result.get(ipv4Result.size() - 1); + } else if (!ipv6Result.isEmpty()) { + return ipv6Result.get(0); + } + //If failed to find,fall back to localhost + final InetAddress localHost = InetAddress.getLocalHost(); + return normalizeHostAddress(localHost); + } catch (SocketException | UnknownHostException e) { + LOG.error("socket or unknown host exception:", e); + } + return null; + } + + public static boolean isValidIPV4Address(String ip) { + + // Regex for digit from 0 to 255. + String zeroTo255 + = "(\\d{1,2}|(0|1)\\" + + "d{2}|2[0-4]\\d|25[0-5])"; + + String regex + = zeroTo255 + "\\." + + zeroTo255 + "\\." + + zeroTo255 + "\\." + + zeroTo255; + + // Compile the ReGex + Pattern p = Pattern.compile(regex); + + // If the IP address is empty, return false + if (ip == null) { + return false; + } + + Matcher m = p.matcher(ip); + + // Return if the IP address matched the ReGex + return m.matches(); + } + + private static void getIpResult(List ipv4Result, List ipv6Result, + Enumeration en) { + while (en.hasMoreElements()) { + final InetAddress address = en.nextElement(); + if (!address.isLoopbackAddress()) { + if (address instanceof Inet6Address) { + ipv6Result.add(normalizeHostAddress(address)); + } else { + ipv4Result.add(normalizeHostAddress(address)); + } + } + } + } + + private static String normalizeHostAddress(final InetAddress localHost) { + if (localHost instanceof Inet6Address) { + return "[" + localHost.getHostAddress() + "]"; + } else { + return localHost.getHostAddress(); + } + } + + + public static String parseChannelRemoteAddr(final Channel channel) { + if (null == channel) { + return ""; + } + SocketAddress remote = channel.remoteAddress(); + final String addr = remote != null ? remote.toString() : ""; + + if (addr.length() > 0) { + int index = addr.lastIndexOf("/"); + if (index >= 0) { + return addr.substring(index + 1); + } + + return addr; + } + + return ""; + } + + public static boolean isValidDomainOrIp(String url, List ipV4ReservedAddrs, List ipV6ReservedAddrs) { + if (StringUtils.isBlank(url)) { + return false; + } + // Engine only need to verify DNS transformed result + if (isValidIp(url)) { + return true; + } + IPAddress ipAddress = domain2Ip(url); + if (ipAddress == null) { + return false; + } + if (ipAddress.isIPv4()) { + return !isReservedIp(ipAddress, ipV4ReservedAddrs); + } else { + return !isReservedIp(ipAddress, ipV6ReservedAddrs); + } + } + + public static boolean isValidIp(String url) { + try { + IPAddressString ipString = new IPAddressString(url); + if (!ipString.isValid()) { + return new IPAddressString(new URL(url).getHost()).isValid(); + } + } catch (Exception e) { + LOG.warn("Invalid URL format url={}", url, e); + return false; + } + return true; + } + + public static IPAddress domain2Ip(String url) { + HostName hostName = new HostName(url); + if (hostName.isValid()) { + return hostName.getAddress(); + } + try { + String host = new URL(url).getHost(); + return new HostName(host).getAddress(); + } catch (MalformedURLException e) { + LOG.error("Invalid URL format url={}", url, e); + return null; + } + } + + private static boolean isReservedIp(IPAddress ipAddress, List reservedIps) { + for (IPAddress address : reservedIps) { + if (address.contains(ipAddress)) { + return true; + } + } + return false; + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/JsonUtils.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/JsonUtils.java new file mode 100644 index 0000000000..42f74ac852 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/JsonUtils.java @@ -0,0 +1,135 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.utils; + +import org.apache.eventmesh.common.exception.JsonException; + +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +/** + * Json serialize or deserialize utils. + */ +public class JsonUtils { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + static { + OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) + .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + } + + /** + * Serialize object to json string. + * + * @param obj obj + * @return json string + */ + public static String serialize(Object obj) { + if (Objects.isNull(obj)) { + return null; + } + try { + return OBJECT_MAPPER.writeValueAsString(obj); + } catch (JsonProcessingException e) { + throw new JsonException("serialize to json error", e); + } + } + + public static byte[] serialize(String topic, Class data) throws JsonProcessingException { + if (Objects.isNull(data)) { + return null; + } + try { + return OBJECT_MAPPER.writeValueAsBytes(data); + } catch (JsonProcessingException e) { + throw new JsonException("serialize to json error", e); + } + } + + /** + * Deserialize json string to object. + * + * @param json json string + * @param clz object class + * @param object type + * @return object + */ + public static T deserialize(String json, Class clz) { + if (StringUtils.isEmpty(json)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(json, clz); + } catch (JsonProcessingException e) { + throw new JsonException("deserialize json string to object error", e); + } + } + + public static T deserialize(Class clazz, byte[] bytes) { + if (bytes == null || bytes.length == 0) { + return null; + } + try { + return OBJECT_MAPPER.readValue(bytes, clazz); + } catch (IOException e) { + throw new JsonException(String.format("deserialize bytes to %s error", clazz), e); + } + } + + /** + * Deserialize json string to object. + * + * @param str json string + * @param typeReference object type reference + * @param object type + * @return object + */ + public static T deserialize(String str, TypeReference typeReference) { + if (StringUtils.isEmpty(str)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(str, typeReference); + } catch (JsonProcessingException e) { + throw new JsonException("deserialize json string to typeReference error", e); + } + } + + public static JsonNode getJsonNode(String json) { + if (StringUtils.isEmpty(json)) { + return null; + } + try { + return OBJECT_MAPPER.readTree(json); + } catch (JsonProcessingException e) { + throw new JsonException("deserialize json string to JsonNode error", e); + } + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/NetUtils.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/NetUtils.java new file mode 100644 index 0000000000..f8f4856c44 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/NetUtils.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.utils; + +import static org.apache.eventmesh.common.Constants.SUCCESS_CODE; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.enums.HttpMethod; + +import org.apache.http.Consts; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.InetSocketAddress; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.net.httpserver.HttpExchange; + +/** + * NetUtils + */ +public class NetUtils { + + private static final Logger logger = LoggerFactory.getLogger(NetUtils.class); + + /** + * Transform the url form string to Map + * + * @param formData + * @return url parameters map + */ + public static Map formData2Dic(String formData) { + Map result = new HashMap<>(); + if (formData == null || formData.trim().length() == 0) { + return result; + } + final String[] items = formData.split(Constants.AND); + Arrays.stream(items).forEach(item -> { + final String[] keyAndVal = item.split(Constants.EQ); + if (keyAndVal.length == 2) { + try { + final String key = URLDecoder.decode(keyAndVal[0], StandardCharsets.UTF_8.name()); + final String val = URLDecoder.decode(keyAndVal[1], StandardCharsets.UTF_8.name()); + result.put(key, val); + } catch (UnsupportedEncodingException e) { + logger.warn("formData2Dic:param decode failed...", e); + } + } + }); + return result; + } + + public static String addressToString(List clients) { + if (clients.isEmpty()) { + return "no session had been closed"; + } + StringBuilder sb = new StringBuilder(); + for (InetSocketAddress addr : clients) { + sb.append(addr).append(Constants.VERTICAL_LINE); + } + return sb.toString(); + } + + public static String parsePostBody(HttpExchange exchange) + throws IOException { + StringBuilder body = new StringBuilder(); + if (HttpMethod.POST.name().equalsIgnoreCase(exchange.getRequestMethod()) + || HttpMethod.PUT.name().equalsIgnoreCase(exchange.getRequestMethod())) { + try (InputStreamReader reader = + new InputStreamReader(exchange.getRequestBody(), Consts.UTF_8)) { + char[] buffer = new char[256]; + int read; + while ((read = reader.read(buffer)) != -1) { + body.append(buffer, 0, read); + } + } + } + return body.toString(); + } + + public static void sendSuccessResponseHeaders(HttpExchange httpExchange) throws IOException { + httpExchange.sendResponseHeaders(SUCCESS_CODE, 0); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/PropertiesUtils.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/PropertiesUtils.java new file mode 100644 index 0000000000..a691b312c3 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/PropertiesUtils.java @@ -0,0 +1,107 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.utils; + +import org.apache.eventmesh.common.Constants; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Properties; + +import com.google.common.base.Preconditions; + +public class PropertiesUtils { + + public static Properties getPropertiesByPrefix(final Properties from, final String prefix) { + + Properties to = new Properties(); + if (StringUtils.isBlank(prefix) || from == null) { + return to; + } + + from.forEach((key, value) -> { + String keyStr = String.valueOf(key); + if (StringUtils.startsWith(keyStr, prefix)) { + String realKey = StringUtils.substring(keyStr, prefix.length()); + String[] hierarchicalKeys = StringUtils.split(realKey, Constants.DOT); + if (hierarchicalKeys != null) { + Properties hierarchical = to; + for (int idx = 0; idx < hierarchicalKeys.length; idx++) { + String hierarchicalKey = hierarchicalKeys[idx]; + if (StringUtils.isBlank(hierarchicalKey)) { + return; + } + if (idx < hierarchicalKeys.length - 1) { + Object pending = hierarchical.get(hierarchicalKey); + if (pending == null) { + hierarchical.put(hierarchicalKey, hierarchical = new Properties()); + } else if (pending instanceof Properties) { + hierarchical = (Properties) pending; + } else { + // Not Properties No need to parse anymore. + return; + } + } else { + hierarchical.put(hierarchicalKey, value); + } + } + } + } + } + ); + return to; + } + + /** + * Load properties from file when file is exist + * + * @param properties + * @param path + * @param cs + * @throws IOException Exception when loading properties, like illegal content, file permission denies + */ + public static void loadPropertiesWhenFileExist(Properties properties, String path, Charset cs) throws IOException { + Preconditions.checkNotNull(properties, "Properties can not be null"); + File file = new File(path); + if (!file.exists()) { + return; + } + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(new FileInputStream(file), cs))) { + properties.load(reader); + } + } + + /** + * Load properties from file when file is exist + * + * @param properties + * @param path + * @throws IOException Exception when loading properties, like illegal content, file permission denies + */ + public static void loadPropertiesWhenFileExist(Properties properties, String path) throws IOException { + loadPropertiesWhenFileExist(properties, path, StandardCharsets.UTF_8); + } +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/RandomStringUtils.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/RandomStringUtils.java new file mode 100644 index 0000000000..bc14554196 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/RandomStringUtils.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.utils; + +import org.apache.commons.text.RandomStringGenerator; + +public class RandomStringUtils { + + private static final RandomStringGenerator RANDOM_NUM_GENERATOR = new RandomStringGenerator.Builder() + .withinRange('0', '9').build(); + + public static String generateNum(int length) { + return RANDOM_NUM_GENERATOR.generate(length); + } + +} diff --git a/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/ThreadUtils.java b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/ThreadUtils.java new file mode 100644 index 0000000000..af69f08508 --- /dev/null +++ b/eventmesh-common/src/main/java/org/apache/eventmesh/common/utils/ThreadUtils.java @@ -0,0 +1,54 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.utils; + +import org.apache.logging.log4j.util.ProcessIdUtil; + +import java.util.concurrent.ThreadLocalRandom; + +public class ThreadUtils { + + private static volatile long currentPID = -1; + + public static void randomSleep(int min, int max) throws Exception { + // nextInt is normally exclusive of the top value, so add 1 to make it inclusive + int random = ThreadLocalRandom.current().nextInt(min, max + 1); + Thread.sleep(random); + + } + + public static void randomSleep(int max) throws Exception { + randomSleep(1, max); + } + + /** + * get current process id. + * + * @return process id + */ + public static long getPID() { + if (currentPID == -1) { + synchronized (ThreadUtils.class) { + if (currentPID == -1) { + currentPID = Long.parseLong(ProcessIdUtil.getProcessId()); + } + } + } + return currentPID; + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/EventMeshMessageTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/EventMeshMessageTest.java new file mode 100644 index 0000000000..b0df5405f3 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/EventMeshMessageTest.java @@ -0,0 +1,74 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +public class EventMeshMessageTest { + + @Test + public void testGetProp() { + EventMeshMessage message = createLiteMessage(); + Assert.assertEquals(2L, message.getProp().size()); + } + + @Test + public void testSetProp() { + EventMeshMessage message = createLiteMessage(); + Map prop = new HashMap<>(); + prop.put("key3", "value3"); + message.setProp(prop); + Assert.assertEquals(1L, message.getProp().size()); + Assert.assertEquals("value3", message.getProp("key3")); + } + + @Test + public void testAddProp() { + EventMeshMessage message = createLiteMessage(); + message.addProp("key3", "value3"); + Assert.assertEquals(3L, message.getProp().size()); + Assert.assertEquals("value1", message.getProp("key1")); + } + + @Test + public void testGetPropKey() { + EventMeshMessage message = createLiteMessage(); + Assert.assertEquals("value1", message.getProp("key1")); + } + + @Test + public void testRemoveProp() { + EventMeshMessage message = createLiteMessage(); + message.removePropIfPresent("key1"); + Assert.assertEquals(1L, message.getProp().size()); + Assert.assertNull(message.getProp("key1")); + } + + private EventMeshMessage createLiteMessage() { + Map prop = new HashMap<>(); + prop.put("key1", "value1"); + prop.put("key2", "value2"); + return EventMeshMessage.builder() + .prop(prop) + .build(); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/config/CommonConfigurationTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/config/CommonConfigurationTest.java new file mode 100644 index 0000000000..f131a85901 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/config/CommonConfigurationTest.java @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.config; + +import java.io.File; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class CommonConfigurationTest { + + private CommonConfiguration configuration; + + @Before + public void before() { + String file = ConfigurationWrapperTest.class.getResource("/configuration.properties").getFile(); + File f = new File(file); + ConfigurationWrapper wraper = new ConfigurationWrapper(f.getParent(), f.getName(), false); + configuration = new CommonConfiguration(wraper); + } + + @Test + public void testInit() { + configuration.init(); + Assert.assertEquals("value1", configuration.getEventMeshEnv()); + Assert.assertEquals("value2", configuration.getEventMeshIDC()); + Assert.assertEquals("3", configuration.getSysID()); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/config/ConfigurationWrapperTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/config/ConfigurationWrapperTest.java new file mode 100644 index 0000000000..56ce9191ce --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/config/ConfigurationWrapperTest.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.config; + +import java.io.File; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class ConfigurationWrapperTest { + + private ConfigurationWrapper wraper; + + @Before + public void before() { + String file = ConfigurationWrapperTest.class.getResource("/configuration.properties").getFile(); + File f = new File(file); + wraper = new ConfigurationWrapper(f.getParent(), f.getName(), false); + } + + @Test + public void testGetProp() { + Assert.assertEquals("value1", wraper.getProp("eventMesh.server.env")); + Assert.assertEquals("value2", wraper.getProp("eventMesh.server.idc")); + } + + @Test(expected = NullPointerException.class) + public void construct() { + ConfigurationWrapper newWrapper = new ConfigurationWrapper(null, "eventmesh.properties", false); + } + +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/file/WatchFileManagerTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/file/WatchFileManagerTest.java new file mode 100644 index 0000000000..614138a4a3 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/file/WatchFileManagerTest.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.file; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Properties; + +import org.junit.Assert; +import org.junit.Test; + +public class WatchFileManagerTest { + + @Test + public void testWatchFile() throws IOException, InterruptedException { + String file = WatchFileManagerTest.class.getResource("/configuration.properties").getFile(); + File f = new File(file); + final FileChangeListener fileChangeListener = new FileChangeListener() { + @Override + public void onChanged(FileChangeContext changeContext) { + Assert.assertEquals(f.getName(), changeContext.getFileName()); + Assert.assertEquals(f.getParent(), changeContext.getDirectoryPath()); + } + + @Override + public boolean support(FileChangeContext changeContext) { + return changeContext.getWatchEvent().context().toString().contains(f.getName()); + } + }; + WatchFileManager.registerFileChangeListener(f.getParent(), fileChangeListener); + + Properties properties = new Properties(); + properties.load(new BufferedReader(new FileReader(file))); + properties.setProperty("eventMesh.server.newAdd", "newAdd"); + FileWriter fw = new FileWriter(file); + properties.store(fw, "newAdd"); + + Thread.sleep(500); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/loadbalance/RandomLoadBalanceSelectorTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/loadbalance/RandomLoadBalanceSelectorTest.java new file mode 100644 index 0000000000..728244117d --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/loadbalance/RandomLoadBalanceSelectorTest.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.loadbalance; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RandomLoadBalanceSelectorTest { + + private RandomLoadBalanceSelector randomLoadBalanceSelector; + + private Logger logger = LoggerFactory.getLogger(RandomLoadBalanceSelectorTest.class); + + @Before + public void befor() { + List address = new ArrayList<>(); + address.add("A"); + address.add("B"); + address.add("C"); + randomLoadBalanceSelector = new RandomLoadBalanceSelector<>(address); + } + + + @Test + public void testSelect() { + Map addressToNum = new HashMap<>(); + for (int i = 0; i < 100; i++) { + String select = randomLoadBalanceSelector.select(); + addressToNum.put(select, addressToNum.getOrDefault(select, 0) + 1); + } + addressToNum.forEach((key, value) -> logger.info("{} : {}", key, value)); + // just assert success if no exception + Assert.assertTrue(true); + } + + @Test + public void testGetType() { + Assert.assertEquals(LoadBalanceType.RANDOM, randomLoadBalanceSelector.getType()); + } +} \ No newline at end of file diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/loadbalance/WeightRandomLoadBalanceSelectorTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/loadbalance/WeightRandomLoadBalanceSelectorTest.java new file mode 100644 index 0000000000..beb5e659e1 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/loadbalance/WeightRandomLoadBalanceSelectorTest.java @@ -0,0 +1,86 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.loadbalance; + +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.summingInt; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.IntStream; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WeightRandomLoadBalanceSelectorTest { + + private Logger logger = LoggerFactory.getLogger(WeightRandomLoadBalanceSelectorTest.class); + + @Test + public void testSelect() throws Exception { + List> weightList = new ArrayList<>(); + weightList.add(new Weight<>("192.168.0.1", 10)); + weightList.add(new Weight<>("192.168.0.2", 20)); + weightList.add(new Weight<>("192.168.0.3", 40)); + WeightRandomLoadBalanceSelector weightRandomLoadBalanceSelector = new WeightRandomLoadBalanceSelector<>(weightList); + Assert.assertEquals(LoadBalanceType.WEIGHT_RANDOM, weightRandomLoadBalanceSelector.getType()); + int testRange = 100_000; + Map addressToNum = IntStream.range(0, testRange) + .mapToObj(i -> weightRandomLoadBalanceSelector.select()) + .collect(groupingBy(Function.identity(), summingInt(i -> 1))); + + addressToNum.forEach((key, value) -> { + logger.info("{}: {}", key, value); + }); + System.out.printf(addressToNum.toString()); + // the error less than 5% + Assert.assertTrue(Math.abs(addressToNum.get("192.168.0.3") - addressToNum.get("192.168.0.2") * 2) < testRange / 20); + Assert.assertTrue(Math.abs(addressToNum.get("192.168.0.3") - addressToNum.get("192.168.0.1") * 4) < testRange / 20); + } + + @Test + public void testSameWeightSelect() throws Exception { + List> weightList = new ArrayList<>(); + weightList.add(new Weight<>("192.168.0.1", 10)); + weightList.add(new Weight<>("192.168.0.2", 10)); + weightList.add(new Weight<>("192.168.0.3", 10)); + WeightRandomLoadBalanceSelector weightRandomLoadBalanceSelector = new WeightRandomLoadBalanceSelector<>(weightList); + Assert.assertEquals(LoadBalanceType.WEIGHT_RANDOM, weightRandomLoadBalanceSelector.getType()); + + int testRange = 100_000; + Map addressToNum = IntStream.range(0, testRange) + .mapToObj(i -> weightRandomLoadBalanceSelector.select()) + .collect(groupingBy(Function.identity(), summingInt(i -> 1))); + + Field field = WeightRandomLoadBalanceSelector.class.getDeclaredField("sameWeightGroup"); + field.setAccessible(true); + boolean sameWeightGroup = (boolean) field.get(weightRandomLoadBalanceSelector); + Assert.assertTrue(sameWeightGroup); + + addressToNum.forEach((key, value) -> { + logger.info("{}: {}", key, value); + }); + // the error less than 5% + Assert.assertTrue(Math.abs(addressToNum.get("192.168.0.3") - addressToNum.get("192.168.0.2")) < testRange / 20); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/loadbalance/WeightRoundRobinLoadBalanceSelectorTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/loadbalance/WeightRoundRobinLoadBalanceSelectorTest.java new file mode 100644 index 0000000000..cf43ee48ef --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/loadbalance/WeightRoundRobinLoadBalanceSelectorTest.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.loadbalance; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WeightRoundRobinLoadBalanceSelectorTest { + + private Logger logger = LoggerFactory.getLogger(WeightRoundRobinLoadBalanceSelectorTest.class); + + private WeightRoundRobinLoadBalanceSelector weightRoundRobinLoadBalanceSelector; + + @Before + public void before() { + List> weightList = new ArrayList<>(); + weightList.add(new Weight<>("A", 10)); + weightList.add(new Weight<>("B", 20)); + weightList.add(new Weight<>("C", 30)); + weightRoundRobinLoadBalanceSelector = new WeightRoundRobinLoadBalanceSelector<>(weightList); + } + + @Test + public void testSelect() { + Map addressToNum = new HashMap<>(); + for (int i = 0; i < 100_000; i++) { + String select = weightRoundRobinLoadBalanceSelector.select(); + addressToNum.put(select, addressToNum.getOrDefault(select, 0) + 1); + } + addressToNum.forEach((key, value) -> { + logger.info("{}: {}", key, value); + }); + Assert.assertTrue(addressToNum.get("B") > addressToNum.get("A")); + Assert.assertTrue(addressToNum.get("C") > addressToNum.get("B")); + } + + @Test + public void testGetType() { + Assert.assertEquals(LoadBalanceType.WEIGHT_ROUND_ROBIN, weightRoundRobinLoadBalanceSelector.getType()); + } +} \ No newline at end of file diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/loadbalance/WeightTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/loadbalance/WeightTest.java new file mode 100644 index 0000000000..bdf7a845f2 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/loadbalance/WeightTest.java @@ -0,0 +1,44 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.loadbalance; + +import org.junit.Assert; +import org.junit.Test; + +public class WeightTest { + + @Test + public void testDecreaseTotal() { + Weight weight = new Weight(null, 0); + weight.decreaseTotal(1); + Assert.assertEquals(-1, weight.getCurrentWeight().get()); + } + + @Test + public void testIncreaseCurrentWeight() { + Weight weight = new Weight(null, 10); + weight.increaseCurrentWeight(); + Assert.assertEquals(10, weight.getCurrentWeight().get()); + } + + @Test + public void testGetCurrentWeight() { + Weight weight = new Weight(null, 0); + Assert.assertEquals(0, weight.getCurrentWeight().get()); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/HttpCommandTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/HttpCommandTest.java new file mode 100644 index 0000000000..962d6c7a79 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/HttpCommandTest.java @@ -0,0 +1,92 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http; + +import static org.mockito.Mockito.when; + +import org.apache.eventmesh.common.protocol.http.body.Body; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; + +@RunWith(MockitoJUnitRunner.class) +public class HttpCommandTest { + + @Mock + private Header header; + + @Mock + private Body body; + + private HttpCommand httpCommand; + + @Before + public void before() { + httpCommand = new HttpCommand("POST", "1.1", "200"); + } + + @Test + public void testCreateHttpCommandResponseWithHeaderAndBody() { + HttpCommand command = httpCommand.createHttpCommandResponse(header, body); + Map headerMap = new HashMap<>(); + headerMap.put("key1", "value1"); + when(header.toMap()).thenReturn(headerMap); + Assert.assertEquals("1.1", command.getHttpVersion()); + Assert.assertEquals("POST", command.getHttpMethod()); + Assert.assertEquals("200", command.getRequestCode()); + Assert.assertEquals("value1", command.getHeader().toMap().get("key1")); + } + + @Test + public void testAbstractDesc() { + HttpCommand command = httpCommand.createHttpCommandResponse(header, body); + String desc = command.abstractDesc(); + Assert.assertTrue(desc.startsWith("httpCommand")); + } + + @Test + public void testSimpleDesc() { + HttpCommand command = httpCommand.createHttpCommandResponse(header, body); + String desc = command.simpleDesc(); + Assert.assertTrue(desc.startsWith("httpCommand")); + } + + @Test + public void testHttpResponse() throws Exception { + HttpCommand command = httpCommand.createHttpCommandResponse(header, body); + DefaultFullHttpResponse response = command.httpResponse(); + Assert.assertEquals("keep-alive", response.headers().get(HttpHeaderNames.CONNECTION)); + } + + @Test + public void testHttpResponseWithREQCmdType() throws Exception { + DefaultFullHttpResponse response = httpCommand.httpResponse(); + Assert.assertNull(response); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/body/BaseResponseBodyTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/body/BaseResponseBodyTest.java new file mode 100644 index 0000000000..4a8850ba09 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/body/BaseResponseBodyTest.java @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.body; + +import static org.hamcrest.CoreMatchers.is; + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.junit.Assert; +import org.junit.Test; + +public class BaseResponseBodyTest { + + @Test + public void testToMap() { + BaseResponseBody body = new BaseResponseBody(); + body.setRetCode(200); + body.setRetMsg("SUCCESS"); + Assert.assertTrue(body.toMap().containsKey(ProtocolKey.RETCODE)); + Assert.assertTrue(body.toMap().containsKey(ProtocolKey.RETMSG)); + Assert.assertTrue(body.toMap().containsKey(ProtocolKey.RESTIME)); + Assert.assertThat(body.toMap().get(ProtocolKey.RETCODE), is(200)); + Assert.assertThat(body.toMap().get(ProtocolKey.RETMSG), is("SUCCESS")); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/BaseRequestHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/BaseRequestHeaderTest.java new file mode 100644 index 0000000000..4768963908 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/BaseRequestHeaderTest.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header; + + +import static org.hamcrest.CoreMatchers.is; + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +public class BaseRequestHeaderTest { + + @Test + public void testToMap() { + Map headerParam = new HashMap<>(); + headerParam.put(ProtocolKey.REQUEST_CODE, "200"); + BaseRequestHeader header = BaseRequestHeader.buildHeader(headerParam); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.REQUEST_CODE)); + Assert.assertThat(header.toMap().get(ProtocolKey.REQUEST_CODE), is("200")); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/BaseResponseHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/BaseResponseHeaderTest.java new file mode 100644 index 0000000000..23dc6540be --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/BaseResponseHeaderTest.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header; + +import static org.hamcrest.CoreMatchers.is; + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.junit.Assert; +import org.junit.Test; + +public class BaseResponseHeaderTest { + + @Test + public void testToMap() { + BaseResponseHeader header = BaseResponseHeader.buildHeader("200"); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.REQUEST_CODE)); + Assert.assertThat(header.toMap().get(ProtocolKey.REQUEST_CODE), is("200")); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/AbstractRequestHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/AbstractRequestHeaderTest.java new file mode 100644 index 0000000000..0726e6f07f --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/AbstractRequestHeaderTest.java @@ -0,0 +1,39 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import org.junit.Assert; + +public class AbstractRequestHeaderTest { + + public void assertMapContent(Header header) { + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.REQUEST_CODE)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.LANGUAGE)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.VERSION)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.ClientInstanceKey.ENV)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.ClientInstanceKey.IDC)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.ClientInstanceKey.SYS)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.ClientInstanceKey.PID)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.ClientInstanceKey.IP)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.ClientInstanceKey.USERNAME)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.ClientInstanceKey.PASSWD)); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/AbstractResponseHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/AbstractResponseHeaderTest.java new file mode 100644 index 0000000000..54e1f0c35d --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/AbstractResponseHeaderTest.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import static org.hamcrest.CoreMatchers.is; + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.header.Header; + +import org.junit.Assert; + +public class AbstractResponseHeaderTest { + + public void assertMapContent(Header header) { + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.REQUEST_CODE)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV)); + Assert.assertTrue(header.toMap().containsKey(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC)); + Assert.assertThat(header.toMap().get(ProtocolKey.REQUEST_CODE), is(200)); + Assert.assertThat(header.toMap().get(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER), is("CLUSTER")); + Assert.assertThat(header.toMap().get(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP), is("127.0.0.1")); + Assert.assertThat(header.toMap().get(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV), is("DEV")); + Assert.assertThat(header.toMap().get(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC), is("IDC")); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/HeartbeatRequestHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/HeartbeatRequestHeaderTest.java new file mode 100644 index 0000000000..c09359e3f5 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/HeartbeatRequestHeaderTest.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + + +import java.util.HashMap; + +import org.junit.Test; + +public class HeartbeatRequestHeaderTest extends AbstractRequestHeaderTest { + + @Test + public void testToMap() { + HeartbeatRequestHeader header = HeartbeatRequestHeader.buildHeader(new HashMap<>()); + assertMapContent(header); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/HeartbeatResponseHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/HeartbeatResponseHeaderTest.java new file mode 100644 index 0000000000..a437b8f707 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/HeartbeatResponseHeaderTest.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import org.junit.Test; + +public class HeartbeatResponseHeaderTest extends AbstractResponseHeaderTest { + + @Test + public void testToMap() { + HeartbeatResponseHeader header = HeartbeatResponseHeader.buildHeader(200, + "CLUSTER", "127.0.0.1", "DEV", "IDC"); + assertMapContent(header); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/RegRequestHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/RegRequestHeaderTest.java new file mode 100644 index 0000000000..24f7eb3855 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/RegRequestHeaderTest.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import java.util.HashMap; + +import org.junit.Test; + +public class RegRequestHeaderTest extends AbstractRequestHeaderTest { + + @Test + public void testToMap() { + RegRequestHeader header = RegRequestHeader.buildHeader(new HashMap<>()); + assertMapContent(header); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/RegResponseHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/RegResponseHeaderTest.java new file mode 100644 index 0000000000..503c6425ed --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/RegResponseHeaderTest.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import org.junit.Test; + +public class RegResponseHeaderTest extends AbstractResponseHeaderTest { + + @Test + public void testToMap() { + RegResponseHeader header = RegResponseHeader.buildHeader(200, + "CLUSTER", "127.0.0.1", "DEV", "IDC"); + assertMapContent(header); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/SubscribeRequestHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/SubscribeRequestHeaderTest.java new file mode 100644 index 0000000000..af79ff03fe --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/SubscribeRequestHeaderTest.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import java.util.HashMap; + +import org.junit.Test; + +public class SubscribeRequestHeaderTest extends AbstractRequestHeaderTest { + + @Test + public void testToMap() { + SubscribeRequestHeader header = SubscribeRequestHeader.buildHeader(new HashMap<>()); + assertMapContent(header); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/SubscribeResponseHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/SubscribeResponseHeaderTest.java new file mode 100644 index 0000000000..9d646338dd --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/SubscribeResponseHeaderTest.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + + +import org.junit.Test; + +public class SubscribeResponseHeaderTest extends AbstractResponseHeaderTest { + + @Test + public void testToMap() { + SubscribeResponseHeader header = SubscribeResponseHeader.buildHeader(200, + "CLUSTER", "127.0.0.1", "DEV", "IDC"); + assertMapContent(header); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/UnRegRequestHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/UnRegRequestHeaderTest.java new file mode 100644 index 0000000000..50b8e8d6ea --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/UnRegRequestHeaderTest.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + + +import java.util.HashMap; + +import org.junit.Test; + +public class UnRegRequestHeaderTest extends AbstractRequestHeaderTest { + + @Test + public void testToMap() { + UnRegRequestHeader header = UnRegRequestHeader.buildHeader(new HashMap<>()); + assertMapContent(header); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/UnRegResponseHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/UnRegResponseHeaderTest.java new file mode 100644 index 0000000000..0c7b016417 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/UnRegResponseHeaderTest.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import org.junit.Test; + +public class UnRegResponseHeaderTest extends AbstractResponseHeaderTest { + + @Test + public void testToMap() { + UnRegResponseHeader header = UnRegResponseHeader.buildHeader(200, + "CLUSTER", "127.0.0.1", "DEV", "IDC"); + assertMapContent(header); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/UnSubscribeRequestHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/UnSubscribeRequestHeaderTest.java new file mode 100644 index 0000000000..562d92d83d --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/UnSubscribeRequestHeaderTest.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + +import java.util.HashMap; + +import org.junit.Test; + +public class UnSubscribeRequestHeaderTest extends AbstractRequestHeaderTest { + + @Test + public void testToMap() { + UnSubscribeRequestHeader header = UnSubscribeRequestHeader.buildHeader(new HashMap<>()); + assertMapContent(header); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/UnSubscribeResponseHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/UnSubscribeResponseHeaderTest.java new file mode 100644 index 0000000000..3e8cb70ed4 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/client/UnSubscribeResponseHeaderTest.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.client; + + +import org.junit.Test; + +public class UnSubscribeResponseHeaderTest extends AbstractResponseHeaderTest { + + @Test + public void testToMap() { + UnSubscribeResponseHeader header = UnSubscribeResponseHeader.buildHeader(200, + "CLUSTER", "127.0.0.1", "DEV", "IDC"); + assertMapContent(header); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/message/PushMessageRequestHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/message/PushMessageRequestHeaderTest.java new file mode 100644 index 0000000000..d683789578 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/message/PushMessageRequestHeaderTest.java @@ -0,0 +1,60 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + +import static org.hamcrest.CoreMatchers.is; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class PushMessageRequestHeaderTest { + + private PushMessageRequestHeader header; + + @Before + public void before() { + Map headerParam = new HashMap<>(); + headerParam.put(ProtocolKey.REQUEST_CODE, 200); + headerParam.put(ProtocolKey.LANGUAGE, Constants.LANGUAGE_JAVA); + headerParam.put(ProtocolKey.VERSION, "1.0"); + headerParam.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER, "default cluster"); + headerParam.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP, "127.0.0.1"); + headerParam.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV, "DEV"); + headerParam.put(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC, "IDC"); + header = PushMessageRequestHeader.buildHeader(headerParam); + } + + @Test + public void testToMap() { + Assert.assertThat(header.toMap().get(ProtocolKey.REQUEST_CODE), is(200)); + Assert.assertThat(header.toMap().get(ProtocolKey.LANGUAGE), is(Constants.LANGUAGE_JAVA)); + Assert.assertThat(header.toMap().get(ProtocolKey.VERSION), is(ProtocolVersion.V1)); + Assert.assertThat(header.toMap().get(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER), is("default cluster")); + Assert.assertThat(header.toMap().get(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP), is("127.0.0.1")); + Assert.assertThat(header.toMap().get(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV), is("DEV")); + Assert.assertThat(header.toMap().get(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC), is("IDC")); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/message/PushMessageResponseHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/message/PushMessageResponseHeaderTest.java new file mode 100644 index 0000000000..3446ef0e2d --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/message/PushMessageResponseHeaderTest.java @@ -0,0 +1,44 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + +import static org.hamcrest.CoreMatchers.is; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; + +import org.junit.Assert; +import org.junit.Test; + +public class PushMessageResponseHeaderTest { + + @Test + public void testToMap() { + PushMessageResponseHeader header = PushMessageResponseHeader.buildHeader(100, "DEV", + "IDC", "SYSID", "PID", "127.0.0.1"); + Assert.assertThat(header.toMap().get(ProtocolKey.REQUEST_CODE), is(100)); + Assert.assertThat(header.toMap().get(ProtocolKey.LANGUAGE), is(Constants.LANGUAGE_JAVA)); + Assert.assertThat(header.toMap().get(ProtocolKey.VERSION), is(ProtocolVersion.V1)); + Assert.assertThat(header.toMap().get(ProtocolKey.ClientInstanceKey.ENV), is("DEV")); + Assert.assertThat(header.toMap().get(ProtocolKey.ClientInstanceKey.IDC), is("IDC")); + Assert.assertThat(header.toMap().get(ProtocolKey.ClientInstanceKey.SYS), is("SYSID")); + Assert.assertThat(header.toMap().get(ProtocolKey.ClientInstanceKey.PID), is("PID")); + Assert.assertThat(header.toMap().get(ProtocolKey.ClientInstanceKey.IP), is("127.0.0.1")); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/message/ReplyMessageRequestHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/message/ReplyMessageRequestHeaderTest.java new file mode 100644 index 0000000000..eec5d1854d --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/message/ReplyMessageRequestHeaderTest.java @@ -0,0 +1,62 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + +import static org.hamcrest.CoreMatchers.is; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; +import org.apache.eventmesh.common.protocol.http.common.ProtocolVersion; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class ReplyMessageRequestHeaderTest { + + private ReplyMessageRequestHeader header; + + @Before + public void before() { + Map headerParam = new HashMap<>(); + headerParam.put(ProtocolKey.REQUEST_CODE, "200"); + headerParam.put(ProtocolKey.LANGUAGE, Constants.LANGUAGE_JAVA); + headerParam.put(ProtocolKey.VERSION, "1.0"); + headerParam.put(ProtocolKey.ClientInstanceKey.ENV, "DEV"); + headerParam.put(ProtocolKey.ClientInstanceKey.IDC, "IDC"); + headerParam.put(ProtocolKey.ClientInstanceKey.SYS, "SYS"); + headerParam.put(ProtocolKey.ClientInstanceKey.PID, "PID"); + headerParam.put(ProtocolKey.ClientInstanceKey.IP, "127.0.0.1"); + header = ReplyMessageRequestHeader.buildHeader(headerParam); + } + + @Test + public void testToMap() { + Assert.assertThat(header.toMap().get(ProtocolKey.REQUEST_CODE), is("200")); + Assert.assertThat(header.toMap().get(ProtocolKey.LANGUAGE), is(Constants.LANGUAGE_JAVA)); + Assert.assertThat(header.toMap().get(ProtocolKey.VERSION), is(ProtocolVersion.V1)); + Assert.assertThat(header.toMap().get(ProtocolKey.ClientInstanceKey.ENV), is("DEV")); + Assert.assertThat(header.toMap().get(ProtocolKey.ClientInstanceKey.IDC), is("IDC")); + Assert.assertThat(header.toMap().get(ProtocolKey.ClientInstanceKey.SYS), is("SYS")); + Assert.assertThat(header.toMap().get(ProtocolKey.ClientInstanceKey.PID), is("PID")); + Assert.assertThat(header.toMap().get(ProtocolKey.ClientInstanceKey.IP), is("127.0.0.1")); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/message/ReplyMessageResponseHeaderTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/message/ReplyMessageResponseHeaderTest.java new file mode 100644 index 0000000000..a6714a885b --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/http/header/message/ReplyMessageResponseHeaderTest.java @@ -0,0 +1,39 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.http.header.message; + +import static org.hamcrest.CoreMatchers.is; + +import org.apache.eventmesh.common.protocol.http.common.ProtocolKey; + +import org.junit.Assert; +import org.junit.Test; + +public class ReplyMessageResponseHeaderTest { + + @Test + public void testToMap() { + ReplyMessageResponseHeader header = ReplyMessageResponseHeader.buildHeader(100, + "Cluster", "127.0.0.1", "DEV", "IDC"); + Assert.assertThat(header.toMap().get(ProtocolKey.REQUEST_CODE), is(100)); + Assert.assertThat(header.toMap().get(ProtocolKey.EventMeshInstanceKey.EVENTMESHCLUSTER), is("Cluster")); + Assert.assertThat(header.toMap().get(ProtocolKey.EventMeshInstanceKey.EVENTMESHIP), is("127.0.0.1")); + Assert.assertThat(header.toMap().get(ProtocolKey.EventMeshInstanceKey.EVENTMESHENV), is("DEV")); + Assert.assertThat(header.toMap().get(ProtocolKey.EventMeshInstanceKey.EVENTMESHIDC), is("IDC")); + } +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/tcp/codec/CodecTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/tcp/codec/CodecTest.java new file mode 100644 index 0000000000..bb66e5c04b --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/protocol/tcp/codec/CodecTest.java @@ -0,0 +1,50 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.protocol.tcp.codec; + +import org.apache.eventmesh.common.protocol.tcp.Command; +import org.apache.eventmesh.common.protocol.tcp.Header; +import org.apache.eventmesh.common.protocol.tcp.Package; + +import java.util.ArrayList; + +import org.junit.Assert; +import org.junit.Test; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.PooledByteBufAllocator; + +public class CodecTest { + + @Test + public void testCodec() throws Exception { + Header header = new Header(); + header.setCmd(Command.HELLO_REQUEST); + Package testP = new Package(header); + testP.setBody(new Object()); + Codec.Encoder ce = new Codec.Encoder(); + ByteBuf buf = PooledByteBufAllocator.DEFAULT.buffer(); + ce.encode(null, testP, buf); + Codec.Decoder cd = new Codec.Decoder(); + ArrayList result = new ArrayList<>(); + cd.decode(null, buf, result); + Assert.assertNotNull(result.get(0)); + Assert.assertEquals(testP.getHeader(), ((Package) result.get(0)).getHeader()); + } + +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/utils/AssertTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/utils/AssertTest.java new file mode 100644 index 0000000000..f6b0b1d547 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/utils/AssertTest.java @@ -0,0 +1,36 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.utils; + +import org.junit.Test; + +/** + * test {@link AssertUtils} + */ +public class AssertTest { + + @Test(expected = IllegalArgumentException.class) + public void testNotNull() { + AssertUtils.notNull(null, "error message"); + } + + @Test(expected = IllegalArgumentException.class) + public void testIsTrue() { + AssertUtils.isTrue(false, "error message"); + } +} \ No newline at end of file diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/utils/IPUtilsTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/utils/IPUtilsTest.java new file mode 100644 index 0000000000..4adff4475d --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/utils/IPUtilsTest.java @@ -0,0 +1,38 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.utils; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.contrib.java.lang.system.EnvironmentVariables; + +public class IPUtilsTest { + + @Test + public void testDockerIP() { + EnvironmentVariables environmentVariables = new EnvironmentVariables(); + environmentVariables.set("docker_host_ip", "dockHostIP"); + Assert.assertEquals("dockHostIP", IPUtils.getLocalAddress()); + } + + @Test + public void testLocalhostIP() { + Assert.assertNotNull(IPUtils.getLocalAddress()); + } + +} diff --git a/eventmesh-common/src/test/java/org/apache/eventmesh/common/utils/PropertiesUtilsTest.java b/eventmesh-common/src/test/java/org/apache/eventmesh/common/utils/PropertiesUtilsTest.java new file mode 100644 index 0000000000..11cef76530 --- /dev/null +++ b/eventmesh-common/src/test/java/org/apache/eventmesh/common/utils/PropertiesUtilsTest.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +package org.apache.eventmesh.common.utils; + +import org.apache.eventmesh.common.config.ConfigurationWrapperTest; + +import java.util.Enumeration; +import java.util.Properties; + +import org.junit.Assert; +import org.junit.Test; + +public class PropertiesUtilsTest { + + private static final String PREFIX = "test."; + + @Test + public void testGetPropertiesByPrefix() { + Properties from = new Properties(); + from.put("a", 2); + from.put(PREFIX + "a", 1); + from.put(PREFIX + "b", 1.0); + from.put(PREFIX + "c.d", "inner d"); + from.put(PREFIX + "c.f", "inner f"); + Properties to = PropertiesUtils.getPropertiesByPrefix(from, PREFIX); + + Assert.assertEquals(3, to.size()); + Assert.assertEquals(2, ((Properties) to.get("c")).size()); + } + + @Test + public void testLoadPropertiesWhenFileExist() { + Properties properties = new Properties(); + String path = ConfigurationWrapperTest.class.getResource("/configuration.properties").getPath(); + try { + PropertiesUtils.loadPropertiesWhenFileExist(properties, path); + Assert.assertEquals(properties.get("eventMesh.server.env").toString(), "value1"); + Assert.assertEquals(properties.get("eventMesh.server.idc").toString(), "value2"); + } catch (Exception e) { + Assert.fail(); + } + } +} diff --git a/eventmesh-common/src/test/resources/configuration.properties b/eventmesh-common/src/test/resources/configuration.properties new file mode 100644 index 0000000000..fe3f749a1b --- /dev/null +++ b/eventmesh-common/src/test/resources/configuration.properties @@ -0,0 +1,29 @@ +# +# 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. +# +eventMesh.server.env=value1 +eventMesh.server.idc=value2 +eventMesh.sysid=3 +eventMesh.server.cluster=value4 +eventMesh.server.name=value5 +eventMesh.server.hostIp=value6 +eventMesh.connector.plugin.type=rocketmq +eventMesh.security.plugin.type=acl +eventMesh.registry.plugin.type=namesrv +eventMesh.registry.plugin.server-addr=127.0.0.1:8848 +eventMesh.registry.plugin.username=nacos +eventMesh.registry.plugin.password=nacos +eventMesh.trace.plugin=zipkin \ No newline at end of file diff --git a/eventmesh-connector-plugin/build.gradle b/eventmesh-connector-plugin/build.gradle new file mode 100644 index 0000000000..d973dcedae --- /dev/null +++ b/eventmesh-connector-plugin/build.gradle @@ -0,0 +1,16 @@ +/* + * 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. + */ \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/build.gradle b/eventmesh-connector-plugin/eventmesh-connector-api/build.gradle new file mode 100644 index 0000000000..25c68d12e6 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/build.gradle @@ -0,0 +1,33 @@ +/* + * 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. + */ + +dependencies { + api project(":eventmesh-spi") + implementation project(":eventmesh-common") + api 'io.cloudevents:cloudevents-core' + api 'io.dropwizard.metrics:metrics-core' + api "io.dropwizard.metrics:metrics-healthchecks" + api "io.dropwizard.metrics:metrics-annotation" + api "io.dropwizard.metrics:metrics-json" + + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + + testCompileOnly 'org.projectlombok:lombok' + testAnnotationProcessor 'org.projectlombok:lombok' + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/gradle.properties b/eventmesh-connector-plugin/eventmesh-connector-api/gradle.properties new file mode 100644 index 0000000000..a9fd83fea0 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/gradle.properties @@ -0,0 +1,16 @@ +# +# 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. +# \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/AbstractContext.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/AbstractContext.java new file mode 100644 index 0000000000..4fa7bd2ecf --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/AbstractContext.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api; + +/** + * AbstractContext + */ +public interface AbstractContext { +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/AsyncConsumeContext.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/AsyncConsumeContext.java new file mode 100644 index 0000000000..7c1c739cd5 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/AsyncConsumeContext.java @@ -0,0 +1,25 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api; + + +public abstract class AsyncConsumeContext { + + public abstract void commit(EventMeshAction action); + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/EventListener.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/EventListener.java new file mode 100644 index 0000000000..eede41ca09 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/EventListener.java @@ -0,0 +1,37 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api; + + +import io.cloudevents.CloudEvent; + +/** + * Event listener, registered for consume messages by consumer. + * + *

+ * + * Thread safe requirements: this interface will be invoked by multi threads, + * so users should keep thread safe during the consume process. + * + *

+ */ +public interface EventListener { + + void consume(final CloudEvent cloudEvent, final AsyncConsumeContext context); + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/EventMeshAction.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/EventMeshAction.java new file mode 100644 index 0000000000..f783201086 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/EventMeshAction.java @@ -0,0 +1,26 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api; + +public enum EventMeshAction { + CommitMessage, + + ReconsumeLater, + + ManualAck +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/EventMeshAsyncConsumeContext.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/EventMeshAsyncConsumeContext.java new file mode 100644 index 0000000000..633a5b712b --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/EventMeshAsyncConsumeContext.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api; + + +public abstract class EventMeshAsyncConsumeContext extends AsyncConsumeContext { + + private AbstractContext abstractContext; + + public AbstractContext getAbstractContext() { + return abstractContext; + } + + public void setAbstractContext(AbstractContext abstractContext) { + this.abstractContext = abstractContext; + } + + public abstract void commit(EventMeshAction action); + +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/LifeCycle.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/LifeCycle.java new file mode 100644 index 0000000000..f5d61de333 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/LifeCycle.java @@ -0,0 +1,36 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api; + +import org.apache.eventmesh.api.consumer.Consumer; +import org.apache.eventmesh.api.producer.Producer; + +/** + * The {@code LifeCycle} defines a lifecycle interface for a OMS related service endpoint, + * like {@link Producer}, {@link Consumer}, and so on. + */ +public interface LifeCycle { + + boolean isStarted(); + + boolean isClosed(); + + void start(); + + void shutdown(); +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/RequestReplyCallback.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/RequestReplyCallback.java new file mode 100644 index 0000000000..9fdfa666bf --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/RequestReplyCallback.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api; + +import io.cloudevents.CloudEvent; + +/** + * RequestReplyCallback + */ +public interface RequestReplyCallback { + + void onSuccess(CloudEvent event); + + void onException(Throwable e); +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/SendCallback.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/SendCallback.java new file mode 100644 index 0000000000..ddbe053d85 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/SendCallback.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api; + +import org.apache.eventmesh.api.exception.OnExceptionContext; +import org.apache.eventmesh.api.producer.Producer; + +import io.cloudevents.CloudEvent; + +/** + * Call back interface used in {@link Producer#publish(CloudEvent, SendCallback)}. + */ +public interface SendCallback { + + void onSuccess(final SendResult sendResult); + + void onException(final OnExceptionContext context); +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/SendResult.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/SendResult.java new file mode 100644 index 0000000000..1a68132c6b --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/SendResult.java @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api; + +public class SendResult { + private String messageId; + + private String topic; + + public String getMessageId() { + return messageId; + } + + public void setMessageId(String messageId) { + this.messageId = messageId; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + @Override + public String toString() { + return "SendResult[topic=" + topic + ", messageId=" + messageId + ']'; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/admin/Admin.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/admin/Admin.java new file mode 100644 index 0000000000..8ccd8aaf6d --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/admin/Admin.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api.admin; + +import org.apache.eventmesh.api.LifeCycle; +import org.apache.eventmesh.spi.EventMeshExtensionType; +import org.apache.eventmesh.spi.EventMeshSPI; + +import java.util.List; +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +/** + * Admin API. + */ +@EventMeshSPI(isSingleton = false, eventMeshExtensionType = EventMeshExtensionType.CONNECTOR) +public interface Admin extends LifeCycle { + /** + * Initializes admin api service. + */ + void init(Properties keyValue) throws Exception; + + /** + * Get the list of topics. + * + * @return List of topics. + */ + List getTopic() throws Exception; + + /** + * Create one topic. + */ + void createTopic(String topicName) throws Exception; + + /** + * Delete one topic. + */ + void deleteTopic(String topicName) throws Exception; + + /** + * Get the list of all events. + * + * @return List of events. + */ + List getEvent(String topicName, int offset, int length) throws Exception; + + /** + * Publish an event. + */ + void publish(CloudEvent cloudEvent) throws Exception; +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/admin/TopicProperties.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/admin/TopicProperties.java new file mode 100644 index 0000000000..06e6266233 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/admin/TopicProperties.java @@ -0,0 +1,38 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api.admin; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class TopicProperties { + public String name; + public long messageCount; + + @JsonCreator + public TopicProperties( + @JsonProperty("name") String name, + @JsonProperty("messageCount") long messageCount + ) { + super(); + this.name = name; + this.messageCount = messageCount; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/connector/ConnectorResourceService.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/connector/ConnectorResourceService.java new file mode 100644 index 0000000000..2657fe5ab2 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/connector/ConnectorResourceService.java @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api.connector; + +import org.apache.eventmesh.spi.EventMeshExtensionType; +import org.apache.eventmesh.spi.EventMeshSPI; + +/** + * ConnectorResourceService + */ +@EventMeshSPI(eventMeshExtensionType = EventMeshExtensionType.CONNECTOR) +public interface ConnectorResourceService { + + /** + * Resource initialization in connector,such as,some public threadpool if exist + * + * @throws Exception + */ + void init() throws Exception; + + /** + * Resource release in connector,such as,some public threadpool if exist + * + * @throws Exception + */ + void release() throws Exception; +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/consumer/Consumer.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/consumer/Consumer.java new file mode 100644 index 0000000000..15fc638ce1 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/consumer/Consumer.java @@ -0,0 +1,46 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api.consumer; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.LifeCycle; +import org.apache.eventmesh.spi.EventMeshExtensionType; +import org.apache.eventmesh.spi.EventMeshSPI; + +import java.util.List; +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +/** + * Consumer Interface. + */ +@EventMeshSPI(isSingleton = false, eventMeshExtensionType = EventMeshExtensionType.CONNECTOR) +public interface Consumer extends LifeCycle { + + void init(Properties keyValue) throws Exception; + + void updateOffset(List cloudEvents, AbstractContext context); + + void subscribe(String topic) throws Exception; + + void unsubscribe(String topic); + + void registerEventListener(EventListener listener); +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/exception/ConnectorRuntimeException.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/exception/ConnectorRuntimeException.java new file mode 100644 index 0000000000..0efe513652 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/exception/ConnectorRuntimeException.java @@ -0,0 +1,38 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api.exception; + +public class ConnectorRuntimeException extends RuntimeException { + + public ConnectorRuntimeException() { + + } + + public ConnectorRuntimeException(String message) { + super(message); + } + + public ConnectorRuntimeException(Throwable throwable) { + super(throwable); + } + + public ConnectorRuntimeException(String message, Throwable throwable) { + super(message, throwable); + } + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/exception/OnExceptionContext.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/exception/OnExceptionContext.java new file mode 100644 index 0000000000..d51da7a0d1 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/exception/OnExceptionContext.java @@ -0,0 +1,39 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api.exception; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OnExceptionContext { + + private String messageId; + + private String topic; + + /** + * Detailed exception stack information. + */ + private ConnectorRuntimeException exception; +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/factory/ConnectorPluginFactory.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/factory/ConnectorPluginFactory.java new file mode 100644 index 0000000000..27adc0fc73 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/factory/ConnectorPluginFactory.java @@ -0,0 +1,64 @@ +/* + * Licensed to 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. Apache Software Foundation (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. + */ + +package org.apache.eventmesh.api.factory; + +import org.apache.eventmesh.api.admin.Admin; +import org.apache.eventmesh.api.consumer.Consumer; +import org.apache.eventmesh.api.producer.Producer; +import org.apache.eventmesh.spi.EventMeshExtensionFactory; + +/** + * The factory to get connector {@link Admin}, {@link Producer} and {@link Consumer} + */ +public class ConnectorPluginFactory { + /** + * Get MeshMQAdmin instance by plugin name + * + * @param connectorPluginName plugin name + * @return MeshMQAdmin instance + */ + public static Admin getMeshMQAdmin(String connectorPluginName) { + return EventMeshExtensionFactory.getExtension(Admin.class, connectorPluginName); + } + + /** + * Get MeshMQProducer instance by plugin name + * + * @param connectorPluginName plugin name + * @return MeshMQProducer instance + */ + public static Producer getMeshMQProducer(String connectorPluginName) { + return EventMeshExtensionFactory.getExtension(Producer.class, connectorPluginName); + } + + /** + * Get MeshMQPushConsumer instance by plugin name + * + * @param connectorPluginName plugin name + * @return MeshMQPushConsumer instance + */ + public static Consumer getMeshMQPushConsumer(String connectorPluginName) { + return EventMeshExtensionFactory.getExtension(Consumer.class, connectorPluginName); + } + + private static T getPlugin(Class pluginType, String pluginName) { + return EventMeshExtensionFactory.getExtension(pluginType, pluginName); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/producer/Producer.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/producer/Producer.java new file mode 100644 index 0000000000..d8fd2b6a7f --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/producer/Producer.java @@ -0,0 +1,50 @@ +/* + * 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. + */ + +package org.apache.eventmesh.api.producer; + +import org.apache.eventmesh.api.LifeCycle; +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.spi.EventMeshExtensionType; +import org.apache.eventmesh.spi.EventMeshSPI; + +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +/** + * Producer Interface. + */ +@EventMeshSPI(isSingleton = false, eventMeshExtensionType = EventMeshExtensionType.CONNECTOR) +public interface Producer extends LifeCycle { + + void init(Properties properties) throws Exception; + + void publish(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception; + + void sendOneway(final CloudEvent cloudEvent); + + void request(CloudEvent cloudEvent, RequestReplyCallback rrCallback, long timeout) throws Exception; + + boolean reply(final CloudEvent cloudEvent, final SendCallback sendCallback) throws Exception; + + void checkTopicExist(String topic) throws Exception; + + void setExtFields(); +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/build.gradle b/eventmesh-connector-plugin/eventmesh-connector-kafka/build.gradle new file mode 100644 index 0000000000..e9b2fa32b8 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/build.gradle @@ -0,0 +1,47 @@ +/* + * 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. + */ +configurations { + implementation.exclude group: 'ch.qos.logback', module: 'logback-classic' + implementation.exclude group: 'log4j', module: 'log4j' +} + +dependencies { + implementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + implementation project(":eventmesh-common") + // https://mavenlibs.com/maven/dependency/io.cloudevents/cloudevents-kafka + implementation group: 'io.cloudevents', name: 'cloudevents-kafka', version: '2.2.1' + + // https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients + implementation 'org.apache.kafka:kafka-clients:3.0.0' + + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' + + testImplementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + testImplementation project(":eventmesh-common") + + testImplementation "org.mockito:mockito-core" + testImplementation "org.powermock:powermock-module-junit4" + testImplementation "org.powermock:powermock-api-mockito2" + + compileOnly 'org.projectlombok:lombok:1.18.22' + compileOnly 'com.google.code.findbugs:jsr305:3.0.1' + annotationProcessor 'org.projectlombok:lombok:1.18.22' + + testCompileOnly 'org.projectlombok:lombok:1.18.22' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.22' +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/gradle.properties b/eventmesh-connector-plugin/eventmesh-connector-kafka/gradle.properties new file mode 100644 index 0000000000..bdede6c8f3 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/gradle.properties @@ -0,0 +1,20 @@ +# 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. +# + +kafka_version=3.2.0 + +pluginType=connector +pluginName=kafka \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/common/Constants.java b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/common/Constants.java new file mode 100644 index 0000000000..32ba705a75 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/common/Constants.java @@ -0,0 +1,23 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.kafka.common; + +public class Constants { + + public static final String BROADCAST_PREFIX = "broadcast-"; +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/common/EventMeshConstants.java b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/common/EventMeshConstants.java new file mode 100644 index 0000000000..c41fedf6dc --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/common/EventMeshConstants.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.kafka.common; + +public class EventMeshConstants { + + public static final String EVENTMESH_CONF_FILE = "kafka-client.properties"; + + public static final int DEFAULT_TIMEOUT_IN_MILLISECONDS = 3000; + + public static final String STORE_TIMESTAMP = "storetime"; +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/config/ClientConfiguration.java b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/config/ClientConfiguration.java new file mode 100644 index 0000000000..f185fcd7cf --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/config/ClientConfiguration.java @@ -0,0 +1,55 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.kafka.config; + +import org.apache.commons.lang3.StringUtils; + +import com.google.common.base.Preconditions; + +public class ClientConfiguration { + + public String namesrvAddr = ""; + public String clientUserName = "username"; + public String clientPass = "password"; + public Integer consumeThreadMin = 2; + public Integer consumeThreadMax = 2; + public Integer consumeQueueSize = 10000; + public Integer pullBatchSize = 32; + public Integer ackWindow = 1000; + public Integer pubWindow = 100; + public long consumeTimeout = 0L; + public Integer pollNameServerInterval = 10 * 1000; + public Integer heartbeatBrokerInterval = 30 * 1000; + public Integer rebalanceInterval = 20 * 1000; + public String clusterName = ""; + public String accessKey = ""; + public String secretKey = ""; + + public void init() { + String namesrvAddrStr = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_KAFKA_SERVER_PORT); + Preconditions.checkState(StringUtils.isNotEmpty(namesrvAddrStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_KAFKA_SERVER_PORT)); + namesrvAddr = StringUtils.trim(namesrvAddrStr); + } + + static class ConfKeys { + + public static String KEYS_EVENTMESH_KAFKA_SERVER_PORT = "eventMesh.server.kafka.port"; + + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/config/ConfigurationWrapper.java b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/config/ConfigurationWrapper.java new file mode 100644 index 0000000000..ecc7d1857c --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/config/ConfigurationWrapper.java @@ -0,0 +1,83 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.kafka.config; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.connector.kafka.common.EventMeshConstants; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@UtilityClass +public class ConfigurationWrapper { + public static final Logger logger = LoggerFactory.getLogger(ConfigurationWrapper.class); + + private static final Properties properties = new Properties(); + + static { + loadProperties(); + } + + public String getProp(String key) { + return StringUtils.isEmpty(key) ? null : properties.getProperty(key, null); + } + + /** + * Load kafka properties file from classpath and conf home. + * The properties defined in conf home will override classpath. + */ + private void loadProperties() { + try (InputStream resourceAsStream = ConfigurationWrapper.class.getResourceAsStream( + "/" + EventMeshConstants.EVENTMESH_CONF_FILE)) { + if (resourceAsStream != null) { + properties.load(resourceAsStream); + } + } catch (IOException e) { + logger.error("Error while loading from classpath:", e); + throw new RuntimeException(String.format("Load %s.properties file from classpath error", EventMeshConstants.EVENTMESH_CONF_FILE)); + } + try { + String configPath = Constants.EVENTMESH_CONF_HOME + File.separator + EventMeshConstants.EVENTMESH_CONF_FILE; + if (new File(configPath).exists()) { + try (FileInputStream fileInputStream = new FileInputStream(configPath); + InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8); + BufferedReader reader = new BufferedReader(inputStreamReader)) { + properties.load(reader); + } + } + } catch (IOException e) { + logger.error("Error while loading from conf home: ", e); + throw new IllegalArgumentException(String.format("Cannot load %s file from conf", EventMeshConstants.EVENTMESH_CONF_FILE)); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/connector/ConnectorResourceServiceKafkaImpl.java b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/connector/ConnectorResourceServiceKafkaImpl.java new file mode 100644 index 0000000000..1140b6e290 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/connector/ConnectorResourceServiceKafkaImpl.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.kafka.connector; + +import org.apache.eventmesh.api.connector.ConnectorResourceService; + +public class ConnectorResourceServiceKafkaImpl implements ConnectorResourceService { + @Override + public void init() throws Exception { + + } + + @Override + public void release() throws Exception { + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/consumer/ConsumerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/consumer/ConsumerImpl.java new file mode 100644 index 0000000000..0301f09154 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/consumer/ConsumerImpl.java @@ -0,0 +1,141 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.kafka.consumer; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.serialization.StringDeserializer; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; +import io.cloudevents.kafka.CloudEventDeserializer; + +public class ConsumerImpl { + public static final Logger logger = LoggerFactory.getLogger(ConsumerImpl.class); + private final KafkaConsumer kafkaConsumer; + private final Properties properties; + private AtomicBoolean started = new AtomicBoolean(false); + private EventListener eventListener; + private KafkaConsumerRunner kafkaConsumerRunner; + private ExecutorService executorService; + private Set topicsSet; + + public ConsumerImpl(final Properties properties) { + Properties props = new Properties(); + + // Other config props + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, properties.getProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG)); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, CloudEventDeserializer.class); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.GROUP_ID_CONFIG, properties.getProperty(ConsumerConfig.GROUP_ID_CONFIG)); + props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false"); + + this.properties = props; + this.kafkaConsumer = new KafkaConsumer(props); + kafkaConsumerRunner = new KafkaConsumerRunner(this.kafkaConsumer); + executorService = Executors.newFixedThreadPool(10); + topicsSet = new HashSet<>(); + } + + public Properties attributes() { + return properties; + } + + public void start() { + if (this.started.compareAndSet(false, true)) { + executorService.submit(kafkaConsumerRunner); + } + } + + + public synchronized void shutdown() { + if (this.started.compareAndSet(true, false)) { + this.kafkaConsumer.close(); + } + } + + + public boolean isStarted() { + return this.started.get(); + } + + + public boolean isClosed() { + return !this.isStarted(); + } + + public KafkaConsumer getKafkaConsumer() { + return kafkaConsumer; + } + + public synchronized void subscribe(String topic) { + try { + // Get the current subscription + topicsSet.add(topic); + List topics = new ArrayList<>(topicsSet); + this.kafkaConsumer.subscribe(topics); + } catch (Exception e) { + logger.error("Error while subscribing the Kafka consumer to topic: ", e); + throw new ConnectorRuntimeException( + String.format("Kafka consumer can't attach to %s.", topic)); + } + } + + public synchronized void unsubscribe(String topic) { + try { + // Kafka will unsubscribe *all* topic if calling unsubscribe, so we + this.kafkaConsumer.unsubscribe(); + topicsSet.remove(topic); + List topics = new ArrayList<>(topicsSet); + this.kafkaConsumer.subscribe(topics); + } catch (Exception e) { + logger.error("Error while unsubscribing the Kafka consumer: ", e); + throw new ConnectorRuntimeException(String.format("kafka push consumer fails to unsubscribe topic: %s", topic)); + } + } + + public void updateOffset(List cloudEvents, AbstractContext context) { + Long maxOffset = cloudEvents.stream().map(cloudEvent -> this.kafkaConsumerRunner.getOffset(cloudEvent)).max(Long::compare).get(); + cloudEvents.forEach(cloudEvent -> this.updateOffset(cloudEvent.getSubject(), maxOffset)); + } + + public void updateOffset(String topicName, long offset) { + this.kafkaConsumer.seek(new TopicPartition(topicName, 1), offset); + } + + public void registerEventListener(EventListener listener) { + this.eventListener = listener; + this.kafkaConsumerRunner.setListener(this.eventListener); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/consumer/KafkaConsumerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/consumer/KafkaConsumerImpl.java new file mode 100644 index 0000000000..8743ef3342 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/consumer/KafkaConsumerImpl.java @@ -0,0 +1,84 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.kafka.consumer; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.consumer.Consumer; + +import org.apache.kafka.clients.consumer.ConsumerConfig; + +import java.util.List; +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +public class KafkaConsumerImpl implements Consumer { + private ConsumerImpl consumer; + + @Override + public synchronized void init(Properties props) throws Exception { + String consumerGroup = props.getProperty("consumerGroup"); + // Other config props + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + + props.put(ConsumerConfig.GROUP_ID_CONFIG, consumerGroup); + consumer = new ConsumerImpl(props); + } + + @Override + public void updateOffset(List cloudEvents, AbstractContext context) { + consumer.updateOffset(cloudEvents, context); + } + + @Override + public void subscribe(String topic) throws Exception { + consumer.subscribe(topic); + } + + @Override + public boolean isStarted() { + return consumer.isStarted(); + } + + @Override + public boolean isClosed() { + return consumer.isClosed(); + } + + @Override + public synchronized void start() { + consumer.start(); + } + + @Override + public void unsubscribe(String topic) { + consumer.unsubscribe(topic); + } + + @Override + public void registerEventListener(EventListener listener) { + consumer.registerEventListener(listener); + } + + @Override + public synchronized void shutdown() { + consumer.shutdown(); + } + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/consumer/KafkaConsumerRunner.java b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/consumer/KafkaConsumerRunner.java new file mode 100644 index 0000000000..26b86e5252 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/consumer/KafkaConsumerRunner.java @@ -0,0 +1,118 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.kafka.consumer; + +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.api.EventMeshAsyncConsumeContext; + +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.common.errors.WakeupException; + +import java.time.Duration; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; + +public class KafkaConsumerRunner implements Runnable { + private final Logger logger = LoggerFactory.getLogger(KafkaConsumerRunner.class); + private final AtomicBoolean closed = new AtomicBoolean(false); + private final KafkaConsumer consumer; + private ConcurrentHashMap cloudEventToOffset; + private EventListener listener; + private AtomicInteger offset; + + public KafkaConsumerRunner(KafkaConsumer kafkaConsumer) { + this.consumer = kafkaConsumer; + cloudEventToOffset = new ConcurrentHashMap<>(); + } + + public synchronized void setListener(EventListener listener) { + this.listener = listener; + } + + public long getOffset(CloudEvent cloudEvent) { + return cloudEventToOffset.getOrDefault(cloudEvent, 0L); + } + + @Override + public void run() { + while (!closed.get()) { + try { + ConsumerRecords records = consumer.poll(Duration.ofMillis(10000)); + // Handle new records + records.forEach(rec -> { + try { + CloudEvent cloudEvent = rec.value(); + String topicName = cloudEvent.getSubject(); + EventMeshAsyncConsumeContext eventMeshAsyncConsumeContext = new EventMeshAsyncConsumeContext() { + @Override + public void commit(EventMeshAction action) { + switch (action) { + case CommitMessage: + // update offset + logger.info("message commit, topic: {}, current offset:{}", topicName, + rec.offset()); + break; + case ReconsumeLater: + // don't update offset + break; + case ManualAck: + // update offset + logger + .info("message ack, topic: {}, current offset:{}", topicName, rec.offset()); + break; + default: + } + } + }; + cloudEventToOffset.put(cloudEvent, rec.offset()); + if (listener != null) { + listener.consume(cloudEvent, eventMeshAsyncConsumeContext); + } + } catch (Exception e) { + logger.info("Error parsing cloudevents: {}", e.getMessage()); + } + }); + } catch (WakeupException e) { + // Ignore exception if closing + if (!closed.get()) { + throw e; + } + } finally { + consumer.close(); + break; + } + } + } + + // Shutdown hook which can be called from a separate thread + public void shutdown() { + closed.set(true); + consumer.wakeup(); + } +} + + + diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/producer/KafkaProducerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/producer/KafkaProducerImpl.java new file mode 100644 index 0000000000..f5c1355b2f --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/producer/KafkaProducerImpl.java @@ -0,0 +1,90 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.kafka.producer; + +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.producer.Producer; + +import org.apache.kafka.clients.producer.ProducerConfig; + +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +public class KafkaProducerImpl implements Producer { + + private ProducerImpl producer; + + @Override + public synchronized void init(Properties keyValue) { + keyValue.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + this.producer = new ProducerImpl(keyValue); + } + + @Override + public boolean isStarted() { + return producer.isStarted(); + } + + @Override + public boolean isClosed() { + return producer.isClosed(); + } + + @Override + public void start() { + producer.start(); + } + + @Override + public synchronized void shutdown() { + producer.shutdown(); + } + + @Override + public void publish(CloudEvent message, SendCallback sendCallback) throws Exception { + producer.sendAsync(message, sendCallback); + } + + @Override + public void request(CloudEvent message, RequestReplyCallback rrCallback, long timeout) throws Exception { + producer.request(message, rrCallback, timeout); + } + + @Override + public boolean reply(final CloudEvent message, final SendCallback sendCallback) throws Exception { + producer.reply(message, sendCallback); + return true; + } + + @Override + public void checkTopicExist(String topic) throws Exception { + this.producer.checkTopicExist(topic); + } + + @Override + public void setExtFields() { + // producer.setExtFields(); + } + + @Override + public void sendOneway(CloudEvent message) { + producer.sendOneway(message); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/producer/ProducerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/producer/ProducerImpl.java new file mode 100644 index 0000000000..a37a303525 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/java/org/apache/eventmesh/connector/kafka/producer/ProducerImpl.java @@ -0,0 +1,118 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.kafka.producer; + +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; + +import org.apache.kafka.clients.admin.Admin; +import org.apache.kafka.clients.producer.KafkaProducer; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.common.serialization.StringSerializer; + +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; +import io.cloudevents.kafka.CloudEventSerializer; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@SuppressWarnings("deprecation") +public class ProducerImpl { + private KafkaProducer producer; + Properties properties; + + private AtomicBoolean isStarted; + + public ProducerImpl(Properties props) { + this.isStarted = new AtomicBoolean(false); + + properties = new Properties(); + properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, + props.getProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG)); + properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, CloudEventSerializer.class); + this.producer = new KafkaProducer<>(properties); + } + + public boolean isStarted() { + return isStarted.get(); + } + + public boolean isClosed() { + return !isStarted.get(); + } + + public void start() { + isStarted.compareAndSet(false, true); + } + + public void shutdown() { + isStarted.compareAndSet(true, false); + } + + public ProducerImpl init(Properties properties) throws Exception { + return new ProducerImpl(properties); + } + + public void send(CloudEvent cloudEvent) { + try { + this.producer.send(new ProducerRecord<>(cloudEvent.getSubject(), cloudEvent)); + } catch (Exception e) { + log.error(String.format("Send message oneway Exception, %s", cloudEvent), e); + } + } + + public void checkTopicExist(String topic) throws ExecutionException, InterruptedException, ConnectorRuntimeException { + Admin admin = Admin.create(properties); + Set topicNames = admin.listTopics().names().get(); + admin.close(); + boolean exist = topicNames.contains(topic); + if (!exist) { + throw new ConnectorRuntimeException(String.format("topic:%s is not exist", topic)); + } + } + + public void request(CloudEvent cloudEvent, RequestReplyCallback rrCallback, long timeout) throws Exception { + throw new ConnectorRuntimeException("Request is not supported"); + } + + public boolean reply(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + throw new ConnectorRuntimeException("Reply is not supported"); + } + + public void sendOneway(CloudEvent message) { + } + + public void sendAsync(CloudEvent cloudEvent, SendCallback sendCallback) { + try { + this.producer.send(new ProducerRecord<>(cloudEvent.getSubject(), cloudEvent)); + } catch (Exception e) { + log.error(String.format("Send message oneway Exception, %s", cloudEvent), e); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService new file mode 100644 index 0000000000..63ebd47c37 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService @@ -0,0 +1,16 @@ +# 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. + +kafka=org.apache.eventmesh.connector.kafka.connector.ConnectorResourceServiceKafkaImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer new file mode 100644 index 0000000000..09ed6cf20b --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer @@ -0,0 +1,16 @@ +# 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. + +kafka=org.apache.eventmesh.connector.kafka.consumer.KafkaConsumerImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer new file mode 100644 index 0000000000..8e7f48a168 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer @@ -0,0 +1,16 @@ +# 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. + +kafka=org.apache.eventmesh.connector.kafka.producer.KafkaProducerImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/resources/kafka-client.properties b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/resources/kafka-client.properties new file mode 100644 index 0000000000..31923d73d6 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/main/resources/kafka-client.properties @@ -0,0 +1,135 @@ +# +# 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. +# +#######################kafka-client################## +eventMesh.server.kafka.namesrvAddr=127.0.0.1:9092;127.0.0.1:9092 +eventMesh.server.kafka.cluster=DefaultCluster +eventMesh.server.kafka.accessKey=******** +eventMesh.server.kafka.secretKey=******** + +# see kafka.server.KafkaConfig for additional details and defaults + +############################# Server Basics ############################# + +# The id of the broker. This must be set to a unique integer for each broker. +broker.id=0 + +############################# Socket Server Settings ############################# + +# The port the socket server listens on +eventMesh.server.kafka.port=9092 +eventMesh.server.kafka.bootstrap.servers=localhost:9092 + +# Hostname the broker will bind to. If not set, the server will bind to all interfaces +#host.name=localhost + +# Hostname the broker will advertise to producers and consumers. If not set, it uses the +# value for "host.name" if configured. Otherwise, it will use the value returned from +# java.net.InetAddress.getCanonicalHostName(). +#advertised.host.name= + +# The port to publish to ZooKeeper for clients to use. If this is not set, +# it will publish the same port that the broker binds to. +#advertised.port= + +# The number of threads handling network requests +num.network.threads=2 + +# The number of threads doing disk I/O +num.io.threads=8 + +# The send buffer (SO_SNDBUF) used by the socket server +socket.send.buffer.bytes=1048576 + +# The receive buffer (SO_RCVBUF) used by the socket server +socket.receive.buffer.bytes=1048576 + +# The maximum size of a request that the socket server will accept (protection against OOM) +socket.request.max.bytes=104857600 + + +############################# Log Basics ############################# + +# A comma seperated list of directories under which to store log files +log.dirs=c:/tmp/kafka-logs/broker0 + +# The default number of log partitions per topic. More partitions allow greater +# parallelism for consumption, but this will also result in more files across +# the brokers. +num.partitions=2 + +############################# Log Flush Policy ############################# + +# Messages are immediately written to the filesystem but by default we only fsync() to sync +# the OS cache lazily. The following configurations control the flush of data to disk. +# There are a few important trade-offs here: +# 1. Durability: Unflushed data may be lost if you are not using replication. +# 2. Latency: Very large flush intervals may lead to latency spikes when the flush does occur as there will be a lot of data to flush. +# 3. Throughput: The flush is generally the most expensive operation, and a small flush interval may lead to exceessive seeks. +# The settings below allow one to configure the flush policy to flush data after a period of time or +# every N messages (or both). This can be done globally and overridden on a per-topic basis. + +# The number of messages to accept before forcing a flush of data to disk +#log.flush.interval.messages=10000 + +# The maximum amount of time a message can sit in a log before we force a flush +#log.flush.interval.ms=1000 + +############################# Log Retention Policy ############################# + +# The following configurations control the disposal of log segments. The policy can +# be set to delete segments after a period of time, or after a given size has accumulated. +# A segment will be deleted whenever *either* of these criteria are met. Deletion always happens +# from the end of the log. + +# The minimum age of a log file to be eligible for deletion +log.retention.hours=168 + +# A size-based retention policy for logs. Segments are pruned from the log as long as the remaining +# segments don't drop below log.retention.bytes. +#log.retention.bytes=1073741824 + +# The maximum size of a log segment file. When this size is reached a new log segment will be created. +log.segment.bytes=536870912 + +# The interval at which log segments are checked to see if they can be deleted according +# to the retention policies +log.retention.check.interval.ms=60000 + +# By default the log cleaner is disabled and the log retention policy will default to just delete segments after their retention expires. +# If log.cleaner.enable=true is set the cleaner will be enabled and individual logs can then be marked for log compaction. +log.cleaner.enable=false + +############################# Zookeeper ############################# + +# Zookeeper connection string (see zookeeper docs for details). +# This is a comma separated host:port pairs, each corresponding to a zk +# server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002". +# You can also append an optional chroot string to the urls to specify the +# root directory for all kafka znodes. +zookeeper.connect=localhost:2181 + +# Timeout in ms for connecting to zookeeper +zookeeper.connection.timeout.ms=1000000 + +############################# Producer Basics ############################# + +# list of brokers used for bootstrapping knowledge about the rest of the cluster +# format: host1:port1,host2:port2 ... +metadata.broker.list=localhost:9092 + +# specifies whether the messages are sent asynchronously (async) or synchronously (sync) +producer.type=async \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/test/resources/META-INF/services/org.apache.io.openmessaging.producer.Producer b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/test/resources/META-INF/services/org.apache.io.openmessaging.producer.Producer new file mode 100644 index 0000000000..358b84da4b --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/test/resources/META-INF/services/org.apache.io.openmessaging.producer.Producer @@ -0,0 +1,20 @@ +# +# 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. +# + +org.apache.eventmesh.connector.kafka.producer.ProducerImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-kafka/src/test/resources/kafka-client.properties b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/test/resources/kafka-client.properties new file mode 100644 index 0000000000..7afdf4c408 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-kafka/src/test/resources/kafka-client.properties @@ -0,0 +1,18 @@ +# +# 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. +# +#######################kafka-client################## +eventMesh.server.kafka.namesrvAddr=127.0.0.1:9092;127.0.0.1:9092 diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/build.gradle b/eventmesh-connector-plugin/eventmesh-connector-knative/build.gradle new file mode 100644 index 0000000000..1eac6bfbe1 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/build.gradle @@ -0,0 +1,40 @@ +/* + * 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. + */ + +dependencies { + implementation 'org.asynchttpclient:async-http-client' + + implementation project(":eventmesh-sdk-java") + testImplementation project(":eventmesh-sdk-java") + + implementation project(":eventmesh-runtime") + testImplementation project(":eventmesh-runtime") + + implementation project(":eventmesh-common") + testImplementation project(":eventmesh-common") + + implementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + testImplementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + + testImplementation "org.powermock:powermock-module-junit4" + + compileOnly 'org.projectlombok:lombok:1.18.22' + annotationProcessor 'org.projectlombok:lombok:1.18.22' + + testCompileOnly 'org.projectlombok:lombok:1.18.22' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.22' +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/gradle.properties b/eventmesh-connector-plugin/eventmesh-connector-knative/gradle.properties new file mode 100644 index 0000000000..27e6abf1c3 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/gradle.properties @@ -0,0 +1,18 @@ +# 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. +# +knative_version=1.5 +pluginType=connector +pluginName=knative \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/cloudevent/KnativeMessageFactory.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/cloudevent/KnativeMessageFactory.java new file mode 100644 index 0000000000..a072f426e6 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/cloudevent/KnativeMessageFactory.java @@ -0,0 +1,47 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.cloudevent; + +import org.apache.eventmesh.connector.knative.cloudevent.impl.KnativeMessageWriter; + +import java.nio.charset.StandardCharsets; +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public final class KnativeMessageFactory { + + private KnativeMessageFactory() { + // prevent instantiation + } + + public static String createReader(final CloudEvent message) { + if (message.getData() == null) { + log.warn("CloudEvent message's data is null."); + return ""; + } + return new String(message.getData().toBytes(), StandardCharsets.UTF_8); + } + + public static KnativeMessageWriter createWriter(final Properties properties) { + return new KnativeMessageWriter(properties); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/cloudevent/impl/KnativeBinaryMessageReader.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/cloudevent/impl/KnativeBinaryMessageReader.java new file mode 100644 index 0000000000..fb7db5b7af --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/cloudevent/impl/KnativeBinaryMessageReader.java @@ -0,0 +1,57 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.cloudevent.impl; + +import java.util.Locale; +import java.util.function.BiConsumer; + +import io.cloudevents.SpecVersion; +import io.cloudevents.core.data.BytesCloudEventData; +import io.cloudevents.core.message.impl.BaseGenericBinaryMessageReaderImpl; + +public class KnativeBinaryMessageReader extends BaseGenericBinaryMessageReaderImpl { + + protected KnativeBinaryMessageReader(SpecVersion version, byte[] body) { + super(version, body != null && body.length > 0 ? BytesCloudEventData.wrap(body) : (BytesCloudEventData) null); + } + + @Override + protected boolean isContentTypeHeader(String key) { + return KnativeHeaders.CONTENT_TYPE.equals(key); + } + + @Override + protected boolean isCloudEventsHeader(String key) { + return true; + } + + @Override + protected String toCloudEventsKey(String key) { + return key.toLowerCase(Locale.getDefault()); + } + + @Override + protected void forEachHeader(BiConsumer fn) { + + } + + @Override + protected String toCloudEventsValue(String value) { + return value; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/cloudevent/impl/KnativeHeaders.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/cloudevent/impl/KnativeHeaders.java new file mode 100644 index 0000000000..f7b0180c09 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/cloudevent/impl/KnativeHeaders.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.cloudevent.impl; + +public class KnativeHeaders { + + public static final String CONTENT_TYPE = "Content-Type"; + + public static final String CE_ID = "Ce-Id"; + + public static final String CE_SPECVERSION = "Ce-Specversion"; + + public static final String CE_TYPE = "Ce-Type"; + + public static final String CE_SOURCE = "Ce-Source"; +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/cloudevent/impl/KnativeMessageWriter.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/cloudevent/impl/KnativeMessageWriter.java new file mode 100644 index 0000000000..4a5ca0ff9e --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/cloudevent/impl/KnativeMessageWriter.java @@ -0,0 +1,80 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.cloudevent.impl; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Properties; + +import io.cloudevents.CloudEvent; +import io.cloudevents.CloudEventData; +import io.cloudevents.SpecVersion; +import io.cloudevents.core.format.EventFormat; +import io.cloudevents.core.message.MessageWriter; +import io.cloudevents.core.v1.CloudEventBuilder; +import io.cloudevents.rw.CloudEventContextWriter; +import io.cloudevents.rw.CloudEventRWException; +import io.cloudevents.rw.CloudEventWriter; + +public class KnativeMessageWriter implements MessageWriter, String>, CloudEventWriter { + + private transient CloudEvent message; + + public CloudEvent getMessage() { + return this.message; + } + + public KnativeMessageWriter(Properties properties) { + String s = "{ \"msg\": [\"" + properties.get("data") + "\"]}"; + this.message = new CloudEventBuilder() + .withId(properties.getProperty(KnativeHeaders.CE_ID)) + .withSource(URI.create(properties.getProperty(KnativeHeaders.CE_SOURCE))) + .withType(properties.getProperty(KnativeHeaders.CE_TYPE)) + .withDataContentType(properties.getProperty(KnativeHeaders.CONTENT_TYPE)) + .withData(s.getBytes(StandardCharsets.UTF_8)) + .build(); + } + + @Override + public String end(CloudEventData data) throws CloudEventRWException { + return data.toString(); + } + + @Override + public String end() throws CloudEventRWException { + if (message != null && message.getData() != null) { + return message.getData().toString(); + } + throw CloudEventRWException.newOther(new IllegalArgumentException("message data is null")); + } + + @Override + public CloudEventContextWriter withContextAttribute(String name, String value) throws CloudEventRWException { + return null; + } + + @Override + public String setEvent(EventFormat format, byte[] value) throws CloudEventRWException { + return null; + } + + @Override + public CloudEventWriter create(SpecVersion version) throws CloudEventRWException { + return null; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/common/EventMeshConstants.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/common/EventMeshConstants.java new file mode 100644 index 0000000000..c1e1f95692 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/common/EventMeshConstants.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.common; + +public class EventMeshConstants { + + public static final String EVENTMESH_CONF_FILE = "knative-client.properties"; + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/config/ClientConfiguration.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/config/ClientConfiguration.java new file mode 100644 index 0000000000..56855b8139 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/config/ClientConfiguration.java @@ -0,0 +1,55 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.config; + +import org.apache.commons.lang3.StringUtils; + +import com.google.common.base.Preconditions; + +public class ClientConfiguration { + + + private transient String emurl; + + private transient String serviceAddr; + + + public String getEmurl() { + return emurl; + } + + public String getServiceAddr() { + return serviceAddr; + } + + public void init() { + String serviceAddrStr = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_KNATIVE_SERVICE_ADDR); + Preconditions.checkState(StringUtils.isNotEmpty(serviceAddrStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_KNATIVE_SERVICE_ADDR)); + serviceAddr = StringUtils.trim(serviceAddrStr); + String[] temp = serviceAddr.split(";"); + emurl = temp[0]; + serviceAddr = temp[1]; + } + + static class ConfKeys { + + public static final String KEYS_EVENTMESH_KNATIVE_SERVICE_ADDR = "eventMesh.server.knative.service"; + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/config/ConfigurationWrapper.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/config/ConfigurationWrapper.java new file mode 100644 index 0000000000..a6433e2cdd --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/config/ConfigurationWrapper.java @@ -0,0 +1,72 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.config; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.utils.PropertiesUtils; +import org.apache.eventmesh.connector.knative.common.EventMeshConstants; + +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Properties; + +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@UtilityClass +public class ConfigurationWrapper { + + private static final Properties properties = new Properties(); + + static { + loadProperties(); + } + + public String getProp(String key) { + return StringUtils.isEmpty(key) ? null : properties.getProperty(key, null); + } + + /** + * Load Knative properties file from classpath and conf home. + * The properties defined in conf home will override classpath. + */ + private void loadProperties() { + try (InputStream resourceAsStream = ConfigurationWrapper.class.getResourceAsStream( + "/" + EventMeshConstants.EVENTMESH_CONF_FILE)) { + if (resourceAsStream != null) { + properties.load(resourceAsStream); + } + } catch (IOException e) { + throw new RuntimeException(String.format("Load %s.properties file from classpath error", EventMeshConstants.EVENTMESH_CONF_FILE), e); + } + + try { + String configPath = Constants.EVENTMESH_CONF_HOME + File.separator + EventMeshConstants.EVENTMESH_CONF_FILE; + if (new File(configPath).exists()) { + PropertiesUtils.loadPropertiesWhenFileExist(properties, configPath, StandardCharsets.UTF_8); + } + } catch (IOException e) { + throw new IllegalArgumentException(String.format("Cannot load %s file from conf", EventMeshConstants.EVENTMESH_CONF_FILE), e); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/connector/ConnectorResourceServiceKnativeImpl.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/connector/ConnectorResourceServiceKnativeImpl.java new file mode 100644 index 0000000000..753438c807 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/connector/ConnectorResourceServiceKnativeImpl.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.connector; + +import org.apache.eventmesh.api.connector.ConnectorResourceService; + +public class ConnectorResourceServiceKnativeImpl implements ConnectorResourceService { + @Override + public void init() throws Exception { + + } + + @Override + public void release() throws Exception { + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/consumer/DefaultConsumer.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/consumer/DefaultConsumer.java new file mode 100644 index 0000000000..9ab853f501 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/consumer/DefaultConsumer.java @@ -0,0 +1,75 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.consumer; + +import static org.asynchttpclient.Dsl.asyncHttpClient; + +import org.apache.eventmesh.connector.knative.patch.EventMeshMessageListenerConcurrently; + +import java.util.concurrent.TimeUnit; + +import org.asynchttpclient.AsyncHttpClient; +import org.asynchttpclient.ListenableFuture; +import org.asynchttpclient.Response; +import org.asynchttpclient.util.HttpConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class DefaultConsumer { + + private static final Logger LOG = LoggerFactory.getLogger(DefaultConsumer.class); + + private transient AsyncHttpClient asyncHttpClient; + + + private transient EventMeshMessageListenerConcurrently messageListener; + + public EventMeshMessageListenerConcurrently getMessageListener() { + return messageListener; + } + + public DefaultConsumer() throws Exception { + this.asyncHttpClient = asyncHttpClient(); + } + + public String pullMessage(String topic, String subscribeUrl) throws Exception { + Preconditions.checkNotNull(topic, "Subscribe item cannot be null"); + Preconditions.checkNotNull(subscribeUrl, "SubscribeUrl cannot be null"); + + // Get event message via HTTP: + String responseBody; + ListenableFuture execute = asyncHttpClient.prepareGet("http://" + subscribeUrl + "/" + topic).execute(); + Response response = execute.get(10, TimeUnit.SECONDS); + + if (response.getStatusCode() == HttpConstants.ResponseStatusCodes.OK_200) { + responseBody = response.getResponseBody(); + LOG.info(responseBody); + return responseBody; + } + throw new IllegalStateException("HTTP response code error: " + response.getStatusCode()); + } + + public void registerMessageListener(EventMeshMessageListenerConcurrently messageListener) { + this.messageListener = messageListener; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/consumer/KnativeConsumerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/consumer/KnativeConsumerImpl.java new file mode 100644 index 0000000000..56062779c5 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/consumer/KnativeConsumerImpl.java @@ -0,0 +1,95 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.consumer; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.consumer.Consumer; +import org.apache.eventmesh.connector.knative.config.ClientConfiguration; + +import java.util.List; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; + +public class KnativeConsumerImpl implements Consumer { + + private static final Logger LOG = LoggerFactory.getLogger(KnativeConsumerImpl.class); + + private transient PullConsumerImpl pullConsumer; + + + + @Override + public synchronized void init(Properties properties) throws Exception { + // Load parameters from properties file: + final ClientConfiguration clientConfiguration = new ClientConfiguration(); + clientConfiguration.init(); + properties.put("emUrl", clientConfiguration.getEmurl()); + properties.put("serviceAddr", clientConfiguration.getServiceAddr()); + + pullConsumer = new PullConsumerImpl(properties); + } + + @Override + public void subscribe(String topic) { + pullConsumer.subscribe(topic); + } + + @Override + public void unsubscribe(String topic) { + try { + pullConsumer.unsubscribe(topic); + } catch (Exception e) { + LOG.error("unsubscribe error", e); + } + } + + @Override + public void registerEventListener(EventListener listener) { + pullConsumer.registerEventListener(listener); + } + + @Override + public void updateOffset(List cloudEvents, AbstractContext context) { + pullConsumer.updateOffset(cloudEvents, context); + } + + @Override + public boolean isStarted() { + return pullConsumer.isStarted(); + } + + @Override + public boolean isClosed() { + return pullConsumer.isClosed(); + } + + @Override + public void start() { + pullConsumer.start(); + } + + @Override + public void shutdown() { + pullConsumer.shutdown(); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/consumer/PullConsumerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/consumer/PullConsumerImpl.java new file mode 100644 index 0000000000..23e2d92ff7 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/consumer/PullConsumerImpl.java @@ -0,0 +1,177 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.consumer; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.api.EventMeshAsyncConsumeContext; +import org.apache.eventmesh.common.protocol.SubscriptionItem; +import org.apache.eventmesh.common.protocol.SubscriptionMode; +import org.apache.eventmesh.common.protocol.SubscriptionType; +import org.apache.eventmesh.connector.knative.domain.NonStandardKeys; +import org.apache.eventmesh.connector.knative.patch.EventMeshConsumeConcurrentlyContext; +import org.apache.eventmesh.connector.knative.patch.EventMeshConsumeConcurrentlyStatus; +import org.apache.eventmesh.connector.knative.patch.EventMeshMessageListenerConcurrently; + +import java.util.List; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; + +import com.google.common.collect.Lists; + +public class PullConsumerImpl { + + private static final Logger LOG = LoggerFactory.getLogger(PullConsumerImpl.class); + + private final transient DefaultConsumer defaultConsumer; + + // Topics to subscribe: + private transient List topicList = null; + private final transient ConcurrentHashMap offsetMap; + private final transient AtomicBoolean started = new AtomicBoolean(false); + private final transient Properties properties; + + // Store received message: + private transient ConcurrentMap subscriptionInner; + private transient EventListener eventListener; + + + + public PullConsumerImpl(final Properties properties) throws Exception { + this.properties = properties; + this.topicList = Lists.newArrayList(); + this.subscriptionInner = new ConcurrentHashMap(); + this.offsetMap = new ConcurrentHashMap<>(); + defaultConsumer = new DefaultConsumer(); + + // Register listener: + defaultConsumer.registerMessageListener(new ClusteringMessageListener()); + } + + public void subscribe(String topic) { + // Subscribe topics: + try { + // Add topic to topicList: + topicList.add(new SubscriptionItem(topic, SubscriptionMode.CLUSTERING, SubscriptionType.ASYNC)); + // Pull event messages iteratively: + topicList.forEach( + item -> { + try { + subscriptionInner.put(item.getTopic(), + defaultConsumer.pullMessage(item.getTopic(), properties.getProperty("serviceAddr"))); + } catch (Exception e) { + LOG.error("store received message error", e); + } + } + ); + } catch (Exception e) { + LOG.error("other error", e); + } + } + + public void unsubscribe(String topic) { + try { + // Unsubscribe topic: + topicList.remove(topic); + } catch (Exception e) { + LOG.error("unsubscribe topic error", e); + } + } + + // todo: offset + public void updateOffset(List cloudEvents, AbstractContext context) { + cloudEvents.forEach(cloudEvent -> this.updateOffset( + cloudEvent.getSubject(), (Long) cloudEvent.getExtension("offset")) + ); + } + + public void updateOffset(String topicMetadata, Long offset) { + offsetMap.computeIfPresent(topicMetadata, (k, v) -> { + v.set(offset); + return v; + }); + } + + public void start() { + this.started.set(true); + } + + public synchronized void shutdown() { + this.started.set(false); + } + + public boolean isStarted() { + return this.started.get(); + } + + public boolean isClosed() { + return !this.isStarted(); + } + + public void registerEventListener(EventListener listener) { + this.eventListener = listener; + } + + // todo: load balancer cluser and broadcast + private class ClusteringMessageListener extends EventMeshMessageListenerConcurrently { + @Override + public EventMeshConsumeConcurrentlyStatus handleMessage(CloudEvent cloudEvent, EventMeshConsumeConcurrentlyContext context) { + final Properties contextProperties = new Properties(); + contextProperties.put(NonStandardKeys.MESSAGE_CONSUME_STATUS, EventMeshConsumeConcurrentlyStatus.RECONSUME_LATER.name()); + + EventMeshAsyncConsumeContext eventMeshAsyncConsumeContext = new EventMeshAsyncConsumeContext() { + @Override + public void commit(EventMeshAction action) { + switch (action) { + case CommitMessage: + contextProperties.put(NonStandardKeys.MESSAGE_CONSUME_STATUS, + EventMeshConsumeConcurrentlyStatus.CONSUME_SUCCESS.name()); + break; + case ReconsumeLater: + contextProperties.put(NonStandardKeys.MESSAGE_CONSUME_STATUS, + EventMeshConsumeConcurrentlyStatus.RECONSUME_LATER.name()); + break; + case ManualAck: + contextProperties.put(NonStandardKeys.MESSAGE_CONSUME_STATUS, + EventMeshConsumeConcurrentlyStatus.CONSUME_FINISH.name()); + break; + default: + break; + } + } + }; + + eventMeshAsyncConsumeContext.setAbstractContext((AbstractContext) context); + + // Consume received message: + eventListener.consume(cloudEvent, eventMeshAsyncConsumeContext); + + return EventMeshConsumeConcurrentlyStatus.valueOf( + contextProperties.getProperty(NonStandardKeys.MESSAGE_CONSUME_STATUS)); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/domain/NonStandardKeys.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/domain/NonStandardKeys.java new file mode 100644 index 0000000000..f8a092f602 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/domain/NonStandardKeys.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.domain; + +/** + * NonStandardKeys + */ +public class NonStandardKeys { + + public static final String MESSAGE_CONSUME_STATUS = "em.message.consume.status"; + +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/patch/EventMeshConsumeConcurrentlyContext.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/patch/EventMeshConsumeConcurrentlyContext.java new file mode 100644 index 0000000000..3576a19666 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/patch/EventMeshConsumeConcurrentlyContext.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.patch; + +public class EventMeshConsumeConcurrentlyContext { + private boolean manualAck = true; + + public boolean isManualAck() { + return manualAck; + } + + public void setManualAck(boolean manualAck) { + this.manualAck = manualAck; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/patch/EventMeshConsumeConcurrentlyStatus.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/patch/EventMeshConsumeConcurrentlyStatus.java new file mode 100644 index 0000000000..a5426e3219 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/patch/EventMeshConsumeConcurrentlyStatus.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.patch; + +public enum EventMeshConsumeConcurrentlyStatus { + /** + * Success consumption + */ + CONSUME_SUCCESS, + /** + * Failure consumption,later try to consume + */ + RECONSUME_LATER, + /** + * Success consumption but ack later manually + */ + CONSUME_FINISH +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/patch/EventMeshMessageListenerConcurrently.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/patch/EventMeshMessageListenerConcurrently.java new file mode 100644 index 0000000000..413e0c792c --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/patch/EventMeshMessageListenerConcurrently.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.patch; + +import io.cloudevents.CloudEvent; + +public abstract class EventMeshMessageListenerConcurrently { + public abstract EventMeshConsumeConcurrentlyStatus handleMessage(CloudEvent cloudEvent, EventMeshConsumeConcurrentlyContext context); +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/producer/AbstractProducer.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/producer/AbstractProducer.java new file mode 100644 index 0000000000..93eb82a08e --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/producer/AbstractProducer.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.producer; + +import static org.asynchttpclient.Dsl.asyncHttpClient; + +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.api.producer.Producer; + +import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.asynchttpclient.AsyncHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; + +public abstract class AbstractProducer implements Producer { + + protected static final Logger LOG = LoggerFactory.getLogger(AbstractProducer.class); + + protected final transient AtomicBoolean started = new AtomicBoolean(false); + protected final transient Properties properties; + private transient AsyncHttpClient asyncHttpClient; + + AbstractProducer(final Properties properties) { + this.properties = properties; + this.asyncHttpClient = asyncHttpClient(); + } + + ConnectorRuntimeException checkProducerException(CloudEvent cloudEvent, Throwable e) { + if (cloudEvent.getData() == null) { + return new ConnectorRuntimeException(String.format("CloudEvent message data does not exist.", e)); + } + return new ConnectorRuntimeException(String.format("Unknown connector runtime exception.", e)); + } + + @Override + public boolean isStarted() { + return started.get(); + } + + @Override + public boolean isClosed() { + return !this.isStarted(); + } + + public AsyncHttpClient getAsyncHttpClient() { + return asyncHttpClient; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/producer/KnativeProducerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/producer/KnativeProducerImpl.java new file mode 100644 index 0000000000..cda05dff0b --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/producer/KnativeProducerImpl.java @@ -0,0 +1,93 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.producer; + +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.api.producer.Producer; +import org.apache.eventmesh.connector.knative.config.ClientConfiguration; + +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +public class KnativeProducerImpl implements Producer { + + private transient ProducerImpl producer; + + @Override + public synchronized void init(Properties properties) throws Exception { + // Load parameters from properties file: + final ClientConfiguration clientConfiguration = new ClientConfiguration(); + clientConfiguration.init(); + + properties.put("url", clientConfiguration.getServiceAddr()); + producer = new ProducerImpl(properties); + } + + @Override + public void publish(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + producer.sendAsync(cloudEvent, sendCallback); + } + + @Override + public boolean isStarted() { + return producer.isStarted(); + } + + @Override + public boolean isClosed() { + return producer.isClosed(); + } + + @Override + public void start() { + throw new ConnectorRuntimeException("Start is not supported"); + } + + @Override + public void shutdown() { + throw new ConnectorRuntimeException("Shutdown is not supported"); + } + + @Override + public void sendOneway(CloudEvent cloudEvent) { + throw new ConnectorRuntimeException("SendOneWay is not supported"); + } + + @Override + public void request(CloudEvent cloudEvent, RequestReplyCallback rrCallback, long timeout) throws Exception { + throw new ConnectorRuntimeException("Request is not supported"); + } + + @Override + public boolean reply(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + throw new ConnectorRuntimeException("Reply is not supported"); + } + + @Override + public void checkTopicExist(String topic) throws Exception { + throw new ConnectorRuntimeException("CheckTopicExist is not supported"); + } + + @Override + public void setExtFields() { + throw new ConnectorRuntimeException("SetExtFields is not supported"); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/producer/ProducerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/producer/ProducerImpl.java new file mode 100644 index 0000000000..f97d8c7529 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/producer/ProducerImpl.java @@ -0,0 +1,128 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.producer; + +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.api.exception.OnExceptionContext; +import org.apache.eventmesh.connector.knative.cloudevent.KnativeMessageFactory; +import org.apache.eventmesh.connector.knative.cloudevent.impl.KnativeHeaders; +import org.apache.eventmesh.connector.knative.utils.CloudEventUtils; + +import java.io.IOException; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +import org.asynchttpclient.ListenableFuture; +import org.asynchttpclient.Response; +import org.asynchttpclient.util.HttpConstants; + +import io.cloudevents.CloudEvent; + +public class ProducerImpl extends AbstractProducer { + + public ProducerImpl(final Properties properties) throws IOException { + super(properties); + } + + public Properties attributes() { + return properties; + } + + public void send(CloudEvent cloudEvent, SendCallback sendCallback) { + // Set HTTP header, body and send CloudEvent message: + try { + ListenableFuture execute = super.getAsyncHttpClient().preparePost("http://" + this.attributes().getProperty("url")) + .addHeader(KnativeHeaders.CONTENT_TYPE, cloudEvent.getDataContentType()) + .addHeader(KnativeHeaders.CE_ID, cloudEvent.getId()) + .addHeader(KnativeHeaders.CE_SPECVERSION, String.valueOf(cloudEvent.getSpecVersion())) + .addHeader(KnativeHeaders.CE_TYPE, cloudEvent.getType()) + .addHeader(KnativeHeaders.CE_SOURCE, String.valueOf(cloudEvent.getSource())) + .setBody(KnativeMessageFactory.createReader(cloudEvent)) + .execute(); + + Response response = execute.get(10, TimeUnit.SECONDS); + if (response.getStatusCode() == HttpConstants.ResponseStatusCodes.OK_200) { + sendCallback.onSuccess(CloudEventUtils.convertSendResult(cloudEvent)); + return; + } + throw new IllegalStateException("HTTP response code error: " + response.getStatusCode()); + } catch (Exception e) { + ConnectorRuntimeException onsEx = ProducerImpl.this.checkProducerException(cloudEvent, e); + OnExceptionContext context = new OnExceptionContext(); + context.setTopic(KnativeMessageFactory.createReader(cloudEvent)); + context.setException(onsEx); + sendCallback.onException(context); + } + } + + public void sendAsync(CloudEvent cloudEvent, SendCallback sendCallback) { + try { + this.send(cloudEvent, sendCallback); + } catch (Exception e) { + //LOG.error("Send cloudevent message Exception", e); + throw new ConnectorRuntimeException("Send cloudevent message Exception.", e); + } + } + + @Override + public void init(Properties properties) throws Exception { + new ProducerImpl(properties); + } + + @Override + public void publish(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + this.sendAsync(cloudEvent, sendCallback); + } + + @Override + public void sendOneway(CloudEvent cloudEvent) { + throw new ConnectorRuntimeException("SendOneWay is not supported"); + } + + @Override + public void request(CloudEvent cloudEvent, RequestReplyCallback rrCallback, long timeout) throws Exception { + throw new ConnectorRuntimeException("Request is not supported"); + } + + @Override + public boolean reply(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + throw new ConnectorRuntimeException("Reply is not supported"); + } + + @Override + public void checkTopicExist(String topic) throws Exception { + throw new ConnectorRuntimeException("CheckTopicExist is not supported"); + } + + @Override + public void setExtFields() { + throw new ConnectorRuntimeException("SetExtFields is not supported"); + } + + @Override + public void start() { + started.set(true); + } + + @Override + public void shutdown() { + started.set(false); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/utils/CloudEventUtils.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/utils/CloudEventUtils.java new file mode 100644 index 0000000000..c742c4d768 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/java/org/apache/eventmesh/connector/knative/utils/CloudEventUtils.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.utils; + +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.connector.knative.cloudevent.KnativeMessageFactory; + +import io.cloudevents.CloudEvent; + +public class CloudEventUtils { + + public static SendResult convertSendResult(CloudEvent cloudEvent) { + SendResult sendResult = new SendResult(); + sendResult.setTopic(KnativeMessageFactory.createReader(cloudEvent)); + sendResult.setMessageId(cloudEvent.getId()); + return sendResult; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService new file mode 100644 index 0000000000..9e1ac4a576 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService @@ -0,0 +1,16 @@ +# 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. + +knative=org.apache.eventmesh.connector.knative.connector.ConnectorResourceServiceKnativeImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer new file mode 100644 index 0000000000..f5ac600fa6 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer @@ -0,0 +1,16 @@ +# 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. + +knative=org.apache.eventmesh.connector.knative.consumer.KnativeConsumerImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer new file mode 100644 index 0000000000..ee49fc4e12 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer @@ -0,0 +1,16 @@ +# 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. + +knative=org.apache.eventmesh.connector.knative.producer.KnativeProducerImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/resources/knative-client.properties b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/resources/knative-client.properties new file mode 100644 index 0000000000..8fec1c4302 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/main/resources/knative-client.properties @@ -0,0 +1,18 @@ +# +# 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. +# +#######################knative-client################## +eventMesh.server.knative.service=127.0.0.1;cloudevents-player.default.127.0.0.1.sslip.io diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/test/java/org/apache/eventmesh/connector/knative/consumer/KnativeConsumerImplTest.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/test/java/org/apache/eventmesh/connector/knative/consumer/KnativeConsumerImplTest.java new file mode 100644 index 0000000000..e5edc1261c --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/test/java/org/apache/eventmesh/connector/knative/consumer/KnativeConsumerImplTest.java @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.consumer; + +import java.util.Properties; + +import org.junit.Assert; +import org.junit.Test; + +public class KnativeConsumerImplTest { + + @Test + public void testSubscribe() throws Exception { + Properties properties = new Properties(); + final String topic = "messages"; + properties.put("topic", topic); + + // Create a Knative consumer: + KnativeConsumerImpl knativeConsumer = new KnativeConsumerImpl(); + + try { + knativeConsumer.init(properties); + + // Subscribe: + knativeConsumer.subscribe(properties.getProperty("topic")); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-knative/src/test/java/org/apache/eventmesh/connector/knative/producer/KnativeProducerImplTest.java b/eventmesh-connector-plugin/eventmesh-connector-knative/src/test/java/org/apache/eventmesh/connector/knative/producer/KnativeProducerImplTest.java new file mode 100644 index 0000000000..85c459beb5 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-knative/src/test/java/org/apache/eventmesh/connector/knative/producer/KnativeProducerImplTest.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.knative.producer; + +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.api.exception.OnExceptionContext; +import org.apache.eventmesh.connector.knative.cloudevent.KnativeMessageFactory; +import org.apache.eventmesh.connector.knative.cloudevent.impl.KnativeHeaders; + +import java.util.Properties; + +import org.junit.Assert; +import org.junit.Test; + +public class KnativeProducerImplTest { + + @Test + public void testPublish() throws Exception { + Properties properties = new Properties(); + + properties.put(KnativeHeaders.CONTENT_TYPE, "application/json"); + properties.put(KnativeHeaders.CE_ID, "1234"); + properties.put(KnativeHeaders.CE_SPECVERSION, "1.0"); + properties.put(KnativeHeaders.CE_TYPE, "some-type"); + properties.put(KnativeHeaders.CE_SOURCE, "java-client"); + properties.put("data", "Hello Knative from EventMesh!"); + + // Create a Knative producer: + KnativeProducerImpl knativehProducer = new KnativeProducerImpl(); + + try { + knativehProducer.init(properties); + + // Publish an event message: + knativehProducer.publish(KnativeMessageFactory.createWriter(properties).getMessage(), new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + } + + @Override + public void onException(OnExceptionContext context) { + } + }); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/README.md b/eventmesh-connector-plugin/eventmesh-connector-pravega/README.md new file mode 100644 index 0000000000..6182a5dfd7 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/README.md @@ -0,0 +1,19 @@ +# Pravega Connector +Pravega connector of EventMesh supports taking Pravega as event storage. [Pravega](https://cncf.pravega.io/) is a storage system that exposes Stream as the main primitive for continuous and unbounded data and meets the requirement of EventMesh connector module. + +## The Design of Pravega Connector +Pravega has 3 level storage concepts, which are **Event**, **Stream**, **Scope**. An **Event** is represented as a set of bytes within a Stream. A **Stream** is a durable, elastic, append-only, unbounded sequence of bytes having good performance and strong consistency. A **Scope** acts as a namespace for Stream names and all Stream names are unique within their Scope. + +Naturally, Pravega connector makes each topic correspond to a pravega stream. Because `EventStreamWriter` and `EventStreamReader` must assign to a special stream in a special scope, each topic corresponds to an `EventStreamWriter` and a `ReaderGroup`(only contains one `EventStreamReader`) as well. What's more, `SubscribeTask` thread will read every topic stream continuously. + +**Note**: +- Publish success will respond `-1` as messageId since writing to Pravega will not return message offset of the stream. If you want to use EventMesh with Pravega, please ensure messageId is unimportant. +- Name and ID in Pravega must be `0-9`, `A-Z`, `a-z`, `.`, `-`. + - Topic must be legal in Pravega. + - ReaderGroup name format is `String.format("%s-%s", consumerGroup, topic)` for cluster message model, while random UUID for broadcast message model. + - Reader name format is `String.format("%s-reader", instanceName).replaceAll("\\(", "-").replaceAll("\\)", "-")`. The `instanceName` consists of `consumerGroup`, config `eventMesh.server.cluster`, EventMesh version and PID. + +![pravega-connector](./pravega-connector.jpg) + +## Active Pravega Connector +Referring to doc [_Build and Load Plugins_](https://eventmesh.apache.org/docs/installation/runtime#13-build-and-load-plugins) to load `:eventmesh-connector-plugin:eventmesh-connector-pravega` plugin module, and edit `eventMesh.connector.plugin.type=pravega` in config file `eventmesh.properties` to active pravega connector. \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/build.gradle b/eventmesh-connector-plugin/eventmesh-connector-pravega/build.gradle new file mode 100644 index 0000000000..c6650440fe --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/build.gradle @@ -0,0 +1,39 @@ +/* + * 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. + */ + +configurations { + implementation.exclude group: 'ch.qos.logback', module: 'logback-classic' + implementation.exclude group: 'log4j', module: 'log4j' +} + +dependencies { + implementation project(":eventmesh-common") + implementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + implementation("io.pravega:pravega-client:$pravega_version") { + exclude group: 'io.netty', module: 'netty-codec-http2:4.1.30.Final' + } + // use newer version to avoid CVE + implementation 'io.netty:netty-codec-http2' + + testImplementation "org.testcontainers:testcontainers:1.17.3" + + compileOnly 'org.projectlombok:lombok:1.18.22' + annotationProcessor 'org.projectlombok:lombok:1.18.22' + + testCompileOnly 'org.projectlombok:lombok:1.18.22' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.22' +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/gradle.properties b/eventmesh-connector-plugin/eventmesh-connector-pravega/gradle.properties new file mode 100644 index 0000000000..a5ea881f6f --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/gradle.properties @@ -0,0 +1,20 @@ +# 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. +# + +pravega_version=0.11.0 + +pluginType=connector +pluginName=pravega \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/pravega-connector.jpg b/eventmesh-connector-plugin/eventmesh-connector-pravega/pravega-connector.jpg new file mode 100644 index 0000000000..20cb829605 Binary files /dev/null and b/eventmesh-connector-plugin/eventmesh-connector-pravega/pravega-connector.jpg differ diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/PravegaConnectorResourceServiceImpl.java b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/PravegaConnectorResourceServiceImpl.java new file mode 100644 index 0000000000..49206036c6 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/PravegaConnectorResourceServiceImpl.java @@ -0,0 +1,36 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pravega; + +import org.apache.eventmesh.api.connector.ConnectorResourceService; +import org.apache.eventmesh.connector.pravega.client.PravegaClient; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PravegaConnectorResourceServiceImpl implements ConnectorResourceService { + @Override + public void init() throws Exception { + PravegaClient.getInstance().start(); + } + + @Override + public void release() throws Exception { + PravegaClient.getInstance().shutdown(); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/PravegaConsumerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/PravegaConsumerImpl.java new file mode 100644 index 0000000000..5c06f6d4ad --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/PravegaConsumerImpl.java @@ -0,0 +1,95 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pravega; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.consumer.Consumer; +import org.apache.eventmesh.connector.pravega.client.PravegaClient; +import org.apache.eventmesh.connector.pravega.exception.PravegaConnectorException; + +import java.util.List; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; + +import io.cloudevents.CloudEvent; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PravegaConsumerImpl implements Consumer { + private static final AtomicBoolean started = new AtomicBoolean(false); + + private boolean isBroadcast; + private String instanceName; + private String consumerGroup; + private PravegaClient client; + private EventListener eventListener; + + @Override + public void init(Properties keyValue) throws Exception { + isBroadcast = Boolean.parseBoolean(keyValue.getProperty("isBroadcast", "false")); + instanceName = keyValue.getProperty("instanceName", ""); + consumerGroup = keyValue.getProperty("consumerGroup", ""); + client = PravegaClient.getInstance(); + } + + @Override + public void start() { + started.compareAndSet(false, true); + } + + @Override + public void shutdown() { + started.compareAndSet(true, false); + } + + @Override + public boolean isStarted() { + return started.get(); + } + + @Override + public boolean isClosed() { + return !started.get(); + } + + @Override + public void updateOffset(List cloudEvents, AbstractContext context) { + throw new UnsupportedOperationException(); + } + + @Override + public void subscribe(String topic) throws Exception { + if (!client.subscribe(topic, isBroadcast, consumerGroup, instanceName, eventListener)) { + throw new PravegaConnectorException(String.format("subscribe topic[%s] fail.", topic)); + } + } + + @Override + public void unsubscribe(String topic) { + if (!client.unsubscribe(topic, isBroadcast, consumerGroup)) { + throw new PravegaConnectorException(String.format("unsubscribe topic[%s] fail.", topic)); + } + } + + @Override + public void registerEventListener(EventListener listener) { + this.eventListener = listener; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/PravegaProducerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/PravegaProducerImpl.java new file mode 100644 index 0000000000..a5aa1d2909 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/PravegaProducerImpl.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pravega; + +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.api.exception.OnExceptionContext; +import org.apache.eventmesh.api.producer.Producer; +import org.apache.eventmesh.connector.pravega.client.PravegaClient; +import org.apache.eventmesh.connector.pravega.exception.PravegaConnectorException; + +import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; + +import io.cloudevents.CloudEvent; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PravegaProducerImpl implements Producer { + private final AtomicBoolean started = new AtomicBoolean(false); + private PravegaClient client; + + @Override + public void init(Properties properties) throws Exception { + client = PravegaClient.getInstance(); + } + + @Override + public void start() { + started.compareAndSet(false, true); + } + + @Override + public void shutdown() { + started.compareAndSet(true, false); + } + + @Override + public boolean isStarted() { + return started.get(); + } + + @Override + public boolean isClosed() { + return !started.get(); + } + + @Override + public void publish(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + try { + SendResult sendResult = client.publish(cloudEvent.getSubject(), cloudEvent); + sendCallback.onSuccess(sendResult); + } catch (Exception e) { + log.error("send message error, topic: {}", cloudEvent.getSubject()); + OnExceptionContext onExceptionContext = OnExceptionContext.builder() + .messageId("-1") + .topic(cloudEvent.getSubject()) + .exception(new ConnectorRuntimeException(e)) + .build(); + sendCallback.onException(onExceptionContext); + } + } + + @Override + public void sendOneway(CloudEvent cloudEvent) { + client.publish(cloudEvent.getSubject(), cloudEvent); + } + + @Override + public void request(CloudEvent cloudEvent, RequestReplyCallback rrCallback, long timeout) throws Exception { + throw new UnsupportedOperationException(); + } + + @Override + public boolean reply(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + throw new UnsupportedOperationException(); + } + + @Override + public void checkTopicExist(String topic) throws Exception { + if (!client.checkTopicExist(topic)) { + throw new PravegaConnectorException(String.format("topic:%s is not exist", topic)); + } + } + + @Override + public void setExtFields() { + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/client/PravegaClient.java b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/client/PravegaClient.java new file mode 100644 index 0000000000..5fd9863200 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/client/PravegaClient.java @@ -0,0 +1,227 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pravega.client; + +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.connector.pravega.config.PravegaConnectorConfig; +import org.apache.eventmesh.connector.pravega.exception.PravegaConnectorException; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import io.cloudevents.CloudEvent; +import io.pravega.client.ClientConfig; +import io.pravega.client.EventStreamClientFactory; +import io.pravega.client.admin.ReaderGroupManager; +import io.pravega.client.admin.StreamManager; +import io.pravega.client.stream.EventStreamReader; +import io.pravega.client.stream.EventStreamWriter; +import io.pravega.client.stream.EventWriterConfig; +import io.pravega.client.stream.ReaderConfig; +import io.pravega.client.stream.ReaderGroupConfig; +import io.pravega.client.stream.StreamConfiguration; +import io.pravega.client.stream.impl.ByteArraySerializer; +import io.pravega.shared.NameUtils; +import io.pravega.shared.security.auth.DefaultCredentials; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PravegaClient { + private final PravegaConnectorConfig config; + private final StreamManager streamManager; + private final EventStreamClientFactory clientFactory; + private final ReaderGroupManager readerGroupManager; + private final Map> writerMap = new ConcurrentHashMap<>(); + private final Map subscribeTaskMap = new ConcurrentHashMap<>(); + + private static PravegaClient instance; + + private PravegaClient(PravegaConnectorConfig config) { + this.config = config; + streamManager = StreamManager.create(config.getControllerURI()); + ClientConfig.ClientConfigBuilder clientConfigBuilder = ClientConfig.builder().controllerURI(config.getControllerURI()); + if (config.isAuthEnabled()) { + clientConfigBuilder.credentials(new DefaultCredentials(config.getPassword(), config.getUsername())); + } + if (config.isTlsEnable()) { + clientConfigBuilder.trustStore(config.getTruststore()).validateHostName(false); + } + ClientConfig clientConfig = clientConfigBuilder.build(); + clientFactory = EventStreamClientFactory.withScope(config.getScope(), clientConfig); + readerGroupManager = ReaderGroupManager.withScope(config.getScope(), clientConfig); + } + + public static PravegaClient getInstance() { + if (instance == null) { + instance = new PravegaClient(PravegaConnectorConfig.getInstance()); + } + return instance; + } + + protected static PravegaClient getNewInstance(PravegaConnectorConfig config) { + return new PravegaClient(config); + } + + public void start() { + if (createScope()) { + log.info("Create Pravega scope[{}] success.", PravegaConnectorConfig.getInstance().getScope()); + } else { + log.info("Pravega scope[{}] has already been created.", PravegaConnectorConfig.getInstance().getScope()); + } + } + + public void shutdown() { + subscribeTaskMap.forEach((topic, task) -> task.stopRead()); + subscribeTaskMap.clear(); + writerMap.forEach((topic, writer) -> writer.close()); + writerMap.clear(); + readerGroupManager.close(); + clientFactory.close(); + streamManager.close(); + } + + /** + * Publish CloudEvent to Pravega stream named topic. Note that the messageId in SendResult is always -1 + * since {@link EventStreamWriter#writeEvent(Object)} just return {@link java.util.concurrent.CompletableFuture} + * with {@link Void} which couldn't get messageId. + * + * @param topic topic + * @param cloudEvent cloudEvent + * @return SendResult whose messageId is always -1 + */ + public SendResult publish(String topic, CloudEvent cloudEvent) { + if (!createStream(topic)) { + log.debug("stream[{}] has already been created.", topic); + } + EventStreamWriter writer = writerMap.computeIfAbsent(topic, k -> createWrite(topic)); + PravegaCloudEventWriter cloudEventWriter = new PravegaCloudEventWriter(topic); + PravegaEvent pravegaEvent = cloudEventWriter.writeBinary(cloudEvent); + try { + writer.writeEvent(PravegaEvent.toByteArray(pravegaEvent)).get(5, TimeUnit.SECONDS); + } catch (ExecutionException | InterruptedException | TimeoutException e) { + log.error(String.format("Write topic[%s] fail.", topic), e); + throw new PravegaConnectorException(String.format("Write topic[%s] fail.", topic)); + } + SendResult sendResult = new SendResult(); + sendResult.setTopic(topic); + // set -1 as messageId since writeEvent method doesn't return it. + sendResult.setMessageId("-1"); + return sendResult; + + } + + public boolean subscribe(String topic, boolean isBroadcast, String consumerGroup, String instanceName, EventListener listener) { + if (subscribeTaskMap.containsKey(topic)) { + return true; + } + String readerGroupName = buildReaderGroupName(isBroadcast, consumerGroup, topic); + createReaderGroup(topic, readerGroupName); + String readerId = buildReaderId(instanceName); + EventStreamReader reader = createReader(readerId, readerGroupName); + SubscribeTask subscribeTask = new SubscribeTask(topic, reader, listener); + subscribeTask.start(); + subscribeTaskMap.put(topic, subscribeTask); + return true; + } + + public boolean unsubscribe(String topic, boolean isBroadcast, String consumerGroup) { + if (!subscribeTaskMap.containsKey(topic)) { + return true; + } + if (!isBroadcast) { + deleteReaderGroup(buildReaderGroupName(false, consumerGroup, topic)); + } + subscribeTaskMap.remove(topic).stopRead(); + return true; + } + + public boolean checkTopicExist(String topic) { + return streamManager.checkStreamExists(config.getScope(), topic); + } + + private boolean createScope() { + return streamManager.createScope(config.getScope()); + } + + private boolean createStream(String topic) { + StreamConfiguration streamConfiguration = StreamConfiguration.builder().build(); + return streamManager.createStream(config.getScope(), topic, streamConfiguration); + } + + private EventStreamWriter createWrite(String topic) { + return clientFactory.createEventWriter(topic, new ByteArraySerializer(), EventWriterConfig.builder().build()); + } + + private String buildReaderGroupName(boolean isBroadcast, String consumerGroup, String topic) { + if (isBroadcast) { + return UUID.randomUUID().toString(); + } else { + return String.format("%s-%s", consumerGroup, topic); + } + } + + private String buildReaderId(String instanceName) { + return String.format("%s-reader", instanceName).replaceAll("\\(", "-").replaceAll("\\)", "-"); + } + + private void createReaderGroup(String topic, String readerGroupName) { + if (!checkTopicExist(topic)) { + createStream(topic); + } + ReaderGroupConfig readerGroupConfig = + ReaderGroupConfig.builder() + .stream(NameUtils.getScopedStreamName(config.getScope(), topic)) + .retentionType(ReaderGroupConfig.StreamDataRetention.AUTOMATIC_RELEASE_AT_LAST_CHECKPOINT) + .build(); + readerGroupManager.createReaderGroup(readerGroupName, readerGroupConfig); + } + + private void deleteReaderGroup(String readerGroup) { + readerGroupManager.deleteReaderGroup(readerGroup); + } + + private EventStreamReader createReader(String readerId, String readerGroup) { + return clientFactory.createReader(readerId, readerGroup, new ByteArraySerializer(), ReaderConfig.builder().build()); + } + + protected StreamManager getStreamManager() { + return streamManager; + } + + protected EventStreamClientFactory getClientFactory() { + return clientFactory; + } + + protected ReaderGroupManager getReaderGroupManager() { + return readerGroupManager; + } + + public Map> getWriterMap() { + return writerMap; + } + + protected Map getSubscribeTaskMap() { + return subscribeTaskMap; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/client/PravegaCloudEventWriter.java b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/client/PravegaCloudEventWriter.java new file mode 100644 index 0000000000..347ea3054a --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/client/PravegaCloudEventWriter.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pravega.client; + +import java.nio.charset.StandardCharsets; + +import io.cloudevents.CloudEventData; +import io.cloudevents.SpecVersion; +import io.cloudevents.core.format.EventFormat; +import io.cloudevents.core.message.MessageWriter; +import io.cloudevents.rw.CloudEventContextWriter; +import io.cloudevents.rw.CloudEventRWException; +import io.cloudevents.rw.CloudEventWriter; + +public class PravegaCloudEventWriter + implements MessageWriter, PravegaEvent>, CloudEventWriter { + + private final PravegaEvent pravegaEvent; + + public PravegaCloudEventWriter(String topic) { + pravegaEvent = new PravegaEvent(); + pravegaEvent.setTopic(topic); + pravegaEvent.setCreateTimestamp(System.currentTimeMillis()); + } + + @Override + public PravegaEvent setEvent(EventFormat format, byte[] value) throws CloudEventRWException { + pravegaEvent.setData(new String(value, StandardCharsets.UTF_8)); + return pravegaEvent; + } + + @Override + public PravegaEvent end(CloudEventData data) throws CloudEventRWException { + pravegaEvent.setData(new String(data.toBytes(), StandardCharsets.UTF_8)); + return pravegaEvent; + } + + @Override + public PravegaEvent end() throws CloudEventRWException { + pravegaEvent.setData(""); + return pravegaEvent; + } + + @Override + public CloudEventContextWriter withContextAttribute(String name, String value) throws CloudEventRWException { + pravegaEvent.getExtensions().put(name, value); + return this; + } + + @Override + public CloudEventWriter create(SpecVersion version) throws CloudEventRWException { + pravegaEvent.setVersion(version); + return this; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/client/PravegaEvent.java b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/client/PravegaEvent.java new file mode 100644 index 0000000000..7da900ab84 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/client/PravegaEvent.java @@ -0,0 +1,76 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pravega.client; + +import org.apache.eventmesh.common.utils.JsonUtils; +import org.apache.eventmesh.connector.pravega.exception.PravegaConnectorException; + +import java.io.Serializable; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import io.cloudevents.CloudEvent; +import io.cloudevents.SpecVersion; +import io.cloudevents.core.builder.CloudEventBuilder; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class PravegaEvent implements Serializable { + private static final long serialVersionUID = 0L; + + private SpecVersion version; + private String topic; + private String data; + private Map extensions = new HashMap<>(); + private long createTimestamp; + + public static byte[] toByteArray(PravegaEvent pravegaEvent) { + return JsonUtils.serialize(pravegaEvent).getBytes(StandardCharsets.UTF_8); + } + + public static PravegaEvent getFromByteArray(byte[] body) { + return JsonUtils.deserialize(new String(body, StandardCharsets.UTF_8), PravegaEvent.class); + } + + public CloudEvent convertToCloudEvent() { + CloudEventBuilder builder; + switch (version) { + case V03: + builder = CloudEventBuilder.v03(); + break; + case V1: + builder = CloudEventBuilder.v1(); + break; + default: + throw new PravegaConnectorException(String.format("CloudEvent version %s does not support.", version)); + } + builder.withData(data.getBytes(StandardCharsets.UTF_8)) + .withId(extensions.remove("id")) + .withSource(URI.create(extensions.remove("source"))) + .withType(extensions.remove("type")) + .withDataContentType(extensions.remove("datacontenttype")) + .withSubject(extensions.remove("subject")); + extensions.forEach(builder::withExtension); + return builder.build(); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/client/SubscribeTask.java b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/client/SubscribeTask.java new file mode 100644 index 0000000000..cb654985d0 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/client/SubscribeTask.java @@ -0,0 +1,87 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pravega.client; + +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.api.EventMeshAsyncConsumeContext; + +import java.util.concurrent.atomic.AtomicBoolean; + +import io.cloudevents.CloudEvent; +import io.pravega.client.stream.EventRead; +import io.pravega.client.stream.EventStreamReader; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SubscribeTask extends Thread { + private final EventStreamReader reader; + private final EventListener listener; + private final AtomicBoolean running = new AtomicBoolean(true); + private final AtomicBoolean continueRead = new AtomicBoolean(true); + + public SubscribeTask(String name, EventStreamReader reader, EventListener listener) { + super(name); + this.reader = reader; + this.listener = listener; + } + + @Override + public void run() { + CloudEvent cloudEvent = null; + while (running.get()) { + if (continueRead.get()) { + EventRead event = reader.readNextEvent(2000); + if (event == null) { + continue; + } + byte[] eventByteArray = event.getEvent(); + if (eventByteArray == null) { + continue; + } + PravegaEvent pravegaEvent = PravegaEvent.getFromByteArray(eventByteArray); + cloudEvent = pravegaEvent.convertToCloudEvent(); + + listener.consume(cloudEvent, new PravegaEventMeshAsyncConsumeContext()); + } else { + listener.consume(cloudEvent, new PravegaEventMeshAsyncConsumeContext()); + } + } + } + + public void stopRead() { + running.compareAndSet(true, false); + } + + private class PravegaEventMeshAsyncConsumeContext extends EventMeshAsyncConsumeContext { + @Override + public void commit(EventMeshAction action) { + switch (action) { + case CommitMessage: + case ReconsumeLater: + continueRead.set(false); + break; + case ManualAck: + continueRead.set(true); + break; + default: + } + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/config/PravegaConnectorConfig.java b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/config/PravegaConnectorConfig.java new file mode 100644 index 0000000000..2954db4c13 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/config/PravegaConnectorConfig.java @@ -0,0 +1,113 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pravega.config; + +import org.apache.commons.lang3.StringUtils; + +import java.net.URI; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class PravegaConnectorConfig { + public static final String EVENTMESH_PRAVEGA_CONTROLLER_URI = "eventMesh.server.pravega.controller.uri"; + public static final String EVENTMESH_PRAVEGA_SCOPE = "eventMesh.server.pravega.scope"; + public static final String EVENTMESH_PRAVEGA_AUTH_ENABLED = "eventMesh.server.pravega.authEnabled"; + public static final String EVENTMESH_PRAVEGA_USERNAME = "eventMesh.server.pravega.username"; + public static final String EVENTMESH_PRAVEGA_PASSWORD = "eventMesh.server.pravega.password"; + public static final String EVENTMESH_PRAVEGA_TLS_ENABLED = "eventMesh.server.pravega.tlsEnabled"; + public static final String EVENTMESH_PRAVEGA_TRUSTSTORE = "eventMesh.server.pravega.truststore"; + public static final String EVENTMESH_PRAVEGA_CLIENTPOOL_SIZE = "eventMesh.server.pravega.clientPool.size"; + public static final String EVENTMESH_PRAVEGA_QUEUE_SIZE = "eventMesh.server.pravega.queue.size"; + + private URI controllerURI = URI.create("tcp://127.0.0.1:9090"); + private String scope = "eventmesh-pravega"; + private int clientPoolSize = 8; + private int queueSize = 512; + private boolean authEnabled = false; + private String username = ""; + private String password = ""; + private boolean tlsEnable = false; + private String truststore = ""; + + private static PravegaConnectorConfig INSTANCE = null; + + private PravegaConnectorConfig() { + } + + public static synchronized PravegaConnectorConfig getInstance() { + if (INSTANCE == null) { + INSTANCE = new PravegaConnectorConfig(); + INSTANCE.init(); + } + return INSTANCE; + } + + private void init() { + String controllerURIStr = PravegaConnectorConfigWrapper.getProp(EVENTMESH_PRAVEGA_CONTROLLER_URI); + if (StringUtils.isNotBlank(controllerURIStr)) { + controllerURI = URI.create(StringUtils.trim(controllerURIStr)); + } + + String scopeStr = PravegaConnectorConfigWrapper.getProp(EVENTMESH_PRAVEGA_SCOPE); + if (StringUtils.isNotBlank(scopeStr)) { + scope = StringUtils.trim(scopeStr); + } + + String authEnableStr = PravegaConnectorConfigWrapper.getProp(EVENTMESH_PRAVEGA_AUTH_ENABLED); + if (StringUtils.isNotBlank(authEnableStr)) { + authEnabled = Boolean.parseBoolean(StringUtils.trim(authEnableStr)); + } + + String usernameStr = PravegaConnectorConfigWrapper.getProp(EVENTMESH_PRAVEGA_USERNAME); + if (StringUtils.isNotBlank(usernameStr)) { + username = StringUtils.trim(usernameStr); + } + + String passwordStr = PravegaConnectorConfigWrapper.getProp(EVENTMESH_PRAVEGA_PASSWORD); + if (StringUtils.isNotBlank(passwordStr)) { + password = StringUtils.trim(passwordStr); + } + + String tlsEnableStr = PravegaConnectorConfigWrapper.getProp(EVENTMESH_PRAVEGA_TLS_ENABLED); + if (StringUtils.isNotBlank(tlsEnableStr)) { + tlsEnable = Boolean.parseBoolean(StringUtils.trim(tlsEnableStr)); + } + + String truststoreStr = PravegaConnectorConfigWrapper.getProp(EVENTMESH_PRAVEGA_TRUSTSTORE); + if (StringUtils.isNotBlank(truststoreStr)) { + truststore = StringUtils.trim(truststoreStr); + } + + String clientPoolSizeStr = PravegaConnectorConfigWrapper.getProp(EVENTMESH_PRAVEGA_CLIENTPOOL_SIZE); + if (StringUtils.isNumeric(clientPoolSizeStr)) { + clientPoolSize = Integer.parseInt(clientPoolSizeStr); + } + + String queueSizeStr = PravegaConnectorConfigWrapper.getProp(EVENTMESH_PRAVEGA_QUEUE_SIZE); + if (StringUtils.isNumeric(queueSizeStr)) { + queueSize = Integer.parseInt(queueSizeStr); + } + + if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) { + authEnabled = true; + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/config/PravegaConnectorConfigWrapper.java b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/config/PravegaConnectorConfigWrapper.java new file mode 100644 index 0000000000..b3553f9214 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/config/PravegaConnectorConfigWrapper.java @@ -0,0 +1,72 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pravega.config; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.utils.PropertiesUtils; + +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@UtilityClass +public class PravegaConnectorConfigWrapper { + public static final String PRAVEGA_CONF_FILE = "pravega-connector.properties"; + + private static final Properties properties = new Properties(); + + static { + loadProperties(); + } + + public String getProp(String key) { + return StringUtils.isEmpty(key) ? null : properties.getProperty(key, null); + } + + /** + * Load Pravega properties file from classpath and conf home. + * The properties defined in conf home will override classpath. + */ + private void loadProperties() { + String path = File.separator + PRAVEGA_CONF_FILE; + try (InputStream resourceAsStream = PravegaConnectorConfigWrapper.class.getResourceAsStream(path)) { + if (resourceAsStream != null) { + properties.load(resourceAsStream); + } + } catch (IOException e) { + log.error("Load {}.properties file from classpath error", path); + throw new RuntimeException(String.format("Load %s.properties file from classpath error", PRAVEGA_CONF_FILE)); + } + String configPath = Constants.EVENTMESH_CONF_HOME + File.separator + PRAVEGA_CONF_FILE; + try { + if (new File(configPath).exists()) { + PropertiesUtils.loadPropertiesWhenFileExist(properties, configPath); + } + } catch (IOException e) { + log.error("Cannot load {} file from conf", configPath); + throw new IllegalArgumentException(String.format("Cannot load %s file from conf", PRAVEGA_CONF_FILE)); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/exception/PravegaConnectorException.java b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/exception/PravegaConnectorException.java new file mode 100644 index 0000000000..c658be6549 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/java/org/apache/eventmesh/connector/pravega/exception/PravegaConnectorException.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pravega.exception; + +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; + +public class PravegaConnectorException extends ConnectorRuntimeException { + public PravegaConnectorException(String message) { + super(message); + } + + public PravegaConnectorException(Throwable throwable) { + super(throwable); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService new file mode 100644 index 0000000000..4ccc7d70cc --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService @@ -0,0 +1,16 @@ +# 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. + +pravega=org.apache.eventmesh.connector.pravega.PravegaConnectorResourceServiceImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer new file mode 100644 index 0000000000..816011506d --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer @@ -0,0 +1,16 @@ +# 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. + +pravega=org.apache.eventmesh.connector.pravega.PravegaConsumerImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer new file mode 100644 index 0000000000..6b12628208 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer @@ -0,0 +1,16 @@ +# 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. + +pravega=org.apache.eventmesh.connector.pravega.PravegaProducerImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/resources/pravega-connector.properties b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/resources/pravega-connector.properties new file mode 100644 index 0000000000..25fa6f0af4 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/main/resources/pravega-connector.properties @@ -0,0 +1,26 @@ +# +# 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. +# +#######################pravega-client################## +eventMesh.server.pravega.controller.uri=tcp://127.0.0.1:9090 +eventMesh.server.pravega.scope=eventmesh-pravega +eventMesh.server.pravega.authEnabled=false +eventMesh.server.pravega.username= +eventMesh.server.pravega.password= +eventMesh.server.pravega.tlsEnabled=false +eventMesh.server.pravega.truststore= +eventMesh.server.pravega.clientPool.size=8 +eventMesh.server.pravega.queue.size=512 \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/test/java/org/apache/eventmesh/connector/pravega/client/PravegaClientTest.java b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/test/java/org/apache/eventmesh/connector/pravega/client/PravegaClientTest.java new file mode 100644 index 0000000000..c1e5da5b4d --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/test/java/org/apache/eventmesh/connector/pravega/client/PravegaClientTest.java @@ -0,0 +1,184 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pravega.client; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.apache.eventmesh.api.AsyncConsumeContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.connector.pravega.config.PravegaConnectorConfig; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.function.Consumer; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.utility.DockerImageName; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; +import io.pravega.client.admin.StreamManager; +import io.pravega.client.stream.ReaderGroupNotFoundException; + +import com.github.dockerjava.api.command.CreateContainerCmd; +import com.github.dockerjava.api.model.PortBinding; + +@Ignore +public class PravegaClientTest { + private StreamManager streamManager; + private PravegaConnectorConfig config; + private URI controllerURI; + + @Rule + public GenericContainer pravega = + new GenericContainer(DockerImageName.parse("pravega/pravega:0.11.0")) + .withExposedPorts(9090, 12345).withEnv("HOST_IP", "127.0.0.1").withCommand("standalone") + .withCreateContainerCmdModifier((Consumer) createContainerCmd -> + createContainerCmd.getHostConfig() + .withPortBindings(PortBinding.parse("9090:9090"), PortBinding.parse("12345:12345"))); + + @Before + public void setUp() { + String host = pravega.getHost(); + int port = pravega.getFirstMappedPort(); + controllerURI = URI.create(String.format("tcp://%s:%d", host, port)); + streamManager = StreamManager.create(controllerURI); + } + + @Test + public void startTest() { + PravegaClient pravegaClient = getNewPravegaClient(); + pravegaClient.start(); + assertTrue(streamManager.checkScopeExists(config.getScope())); + } + + @Test + public void shutdownTest() { + PravegaClient pravegaClient = getNewPravegaClient(); + pravegaClient.start(); + pravegaClient.publish("test1", createCloudEvent()); + pravegaClient.publish("test2", createCloudEvent()); + pravegaClient.publish("test3", createCloudEvent()); + + pravegaClient.shutdown(); + assertTrue(pravegaClient.getSubscribeTaskMap().isEmpty()); + assertTrue(pravegaClient.getWriterMap().isEmpty()); + } + + @Test + public void publishTest() { + PravegaClient pravegaClient = getNewPravegaClient(); + pravegaClient.start(); + pravegaClient.publish("test1", createCloudEvent()); + pravegaClient.publish("test2", createCloudEvent()); + assertTrue(streamManager.checkStreamExists(config.getScope(), "test1")); + assertTrue(streamManager.checkStreamExists(config.getScope(), "test2")); + } + + @Test + public void subscribeTest() { + PravegaClient pravegaClient = getNewPravegaClient(); + pravegaClient.start(); + pravegaClient.subscribe("test1", false, "consumerGroup", "instanceName", new EventListener() { + @Override + public void consume(CloudEvent cloudEvent, AsyncConsumeContext context) { + // do nothing + } + }); + assertNotNull(pravegaClient.getReaderGroupManager().getReaderGroup("test1-consumerGroup")); + assertTrue(pravegaClient.getSubscribeTaskMap().containsKey("test1")); + } + + @Test + public void unsubscribeTest() { + PravegaClient pravegaClient = getNewPravegaClient(); + pravegaClient.unsubscribe("test1", false, "consumerGroup"); + + pravegaClient.start(); + pravegaClient.subscribe("test1", false, "consumerGroup", "instanceName", new EventListener() { + @Override + public void consume(CloudEvent cloudEvent, AsyncConsumeContext context) { + // do nothing + } + }); + pravegaClient.unsubscribe("test1", false, "consumerGroup"); + + assertFalse(pravegaClient.getSubscribeTaskMap().containsKey("test1")); + try { + pravegaClient.getReaderGroupManager().getReaderGroup("test1-consumerGroup"); + } catch (Exception e) { + assertTrue(e instanceof ReaderGroupNotFoundException); + return; + } + fail(); + } + + @Test + public void checkTopicExistTest() { + PravegaClient pravegaClient = getNewPravegaClient(); + pravegaClient.start(); + assertFalse(pravegaClient.checkTopicExist("test1")); + + pravegaClient.publish("test1", createCloudEvent()); + assertTrue(pravegaClient.checkTopicExist("test1")); + } + + private PravegaClient getNewPravegaClient() { + config = PravegaConnectorConfig.getInstance(); + config.setControllerURI(controllerURI); + return PravegaClient.getNewInstance(config); + } + + private CloudEvent createCloudEvent() { + String data = "{\"headers\":{\"content-length\":\"36\",\"Accept\":\"*/*\",\"ip\":\"127.0.0.1:51226\",\"User-Agent\":\"curl/7.83.1\"," + + "\"Host\":\"127.0.0.1:10105\",\"source\":\"127.0.0.1:51226\",\"Content-Type\":\"application/json\"}," + + "\"path\":\"/eventmesh/publish/TEST-TOPIC-HTTP-ASYNC\",\"method\":\"POST\",\"body\":{\"pass\":\"12345678\",\"name\":\"admin\"}}"; + return CloudEventBuilder.v1() + .withId("c61039e1-7884-4d7f-b72f-6c61160a64fc") + .withSource(URI.create("source:127.0.0.1:51226")) + .withType("http_request") + .withDataContentType("application/json") + .withSubject("TEST-TOPIC-HTTP-ASYNC") + .withData(data.getBytes(StandardCharsets.UTF_8)) + .withExtension("reqeventmesh2mqtimestamp", "1659342713460") + .withExtension("ip", "127.0.0.1:51226") + .withExtension("idc", "idc") + .withExtension("protocoldesc", "http") + .withExtension("pid", 2376) + .withExtension("env", "env") + .withExtension("sys", 1234) + .withExtension("ttl", 4000) + .withExtension("producergroup", "em-http-producer") + .withExtension("consumergroup", "em-http-consumer") + .withExtension("passwd", "pass") + .withExtension("bizseqno", "249695004068274968410952665702") + .withExtension("protocoltype", "http") + .withExtension("msgtype", "persistent") + .withExtension("uniqueid", "866012286651006371403062105469") + .withExtension("username", "eventmesh") + .withExtension("reqc2eventmeshtimestamp", "1659342713460") + .build(); + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/test/java/org/apache/eventmesh/connector/pravega/config/PravegaConnectorConfigTest.java b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/test/java/org/apache/eventmesh/connector/pravega/config/PravegaConnectorConfigTest.java new file mode 100644 index 0000000000..ef638a6386 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/test/java/org/apache/eventmesh/connector/pravega/config/PravegaConnectorConfigTest.java @@ -0,0 +1,81 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pravega.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.net.URI; + +import org.junit.BeforeClass; +import org.junit.Test; + +public class PravegaConnectorConfigTest { + + private static PravegaConnectorConfig config; + + @BeforeClass + public static void init() { + config = PravegaConnectorConfig.getInstance(); + } + + @Test + public void getControllerURI() { + assertEquals(URI.create("tcp://127.0.0.1:9090"), config.getControllerURI()); + } + + @Test + public void getScope() { + assertEquals("eventmesh-pravega", config.getScope()); + } + + @Test + public void isAuthEnabled() { + assertFalse(config.isAuthEnabled()); + } + + @Test + public void getUsername() { + assertEquals("", config.getUsername()); + } + + @Test + public void getPassword() { + assertEquals("", config.getPassword()); + } + + @Test + public void isTslEnabled() { + assertFalse(config.isTlsEnable()); + } + + @Test + public void getTruststore() { + assertEquals("", config.getTruststore()); + } + + @Test + public void getClientPoolSize() { + assertEquals(8, config.getClientPoolSize()); + } + + @Test + public void getQueueSize() { + assertEquals(512, config.getQueueSize()); + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pravega/src/test/resources/pravega-connector.properties b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/test/resources/pravega-connector.properties new file mode 100644 index 0000000000..25fa6f0af4 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pravega/src/test/resources/pravega-connector.properties @@ -0,0 +1,26 @@ +# +# 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. +# +#######################pravega-client################## +eventMesh.server.pravega.controller.uri=tcp://127.0.0.1:9090 +eventMesh.server.pravega.scope=eventmesh-pravega +eventMesh.server.pravega.authEnabled=false +eventMesh.server.pravega.username= +eventMesh.server.pravega.password= +eventMesh.server.pravega.tlsEnabled=false +eventMesh.server.pravega.truststore= +eventMesh.server.pravega.clientPool.size=8 +eventMesh.server.pravega.queue.size=512 \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/build.gradle b/eventmesh-connector-plugin/eventmesh-connector-pulsar/build.gradle new file mode 100644 index 0000000000..3c5489c353 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/build.gradle @@ -0,0 +1,45 @@ +/* + * 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. + */ + +configurations { + implementation.exclude group: 'ch.qos.logback', module: 'logback-classic' + implementation.exclude group: 'log4j', module: 'log4j' +} + +dependencies { + implementation project(":eventmesh-common") + implementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + implementation 'org.apache.pulsar:pulsar-client:2.10.1' + + testImplementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + testImplementation project(":eventmesh-common") + testImplementation 'org.apache.pulsar:pulsar-client:2.10.1' + + implementation 'io.cloudevents:cloudevents-json-jackson' + + testImplementation 'io.cloudevents:cloudevents-json-jackson' + + testImplementation "org.mockito:mockito-core" + testImplementation "org.powermock:powermock-module-junit4" + testImplementation "org.powermock:powermock-api-mockito2" + + compileOnly 'org.projectlombok:lombok:1.18.22' + annotationProcessor 'org.projectlombok:lombok:1.18.22' + + testCompileOnly 'org.projectlombok:lombok:1.18.22' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.22' +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/gradle.properties b/eventmesh-connector-plugin/eventmesh-connector-pulsar/gradle.properties new file mode 100644 index 0000000000..9455a2090c --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/gradle.properties @@ -0,0 +1,18 @@ +# 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. +# + +pluginType=connector +pluginName=pulsar \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/client/PulsarClientWrapper.java b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/client/PulsarClientWrapper.java new file mode 100644 index 0000000000..076ca005c5 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/client/PulsarClientWrapper.java @@ -0,0 +1,110 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pulsar.client; + +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.connector.pulsar.config.ClientConfiguration; +import org.apache.eventmesh.connector.pulsar.utils.CloudEventUtils; + +import org.apache.pulsar.client.api.ClientBuilder; +import org.apache.pulsar.client.api.Producer; +import org.apache.pulsar.client.api.PulsarClient; +import org.apache.pulsar.client.api.PulsarClientException; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.provider.EventFormatProvider; +import io.cloudevents.jackson.JsonFormat; + +import com.google.common.base.Preconditions; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PulsarClientWrapper { + + private ClientConfiguration config; + private PulsarClient pulsarClient; + private Map> producerMap = new HashMap<>(); + + public PulsarClientWrapper(ClientConfiguration config) { + this.config = config; + try { + ClientBuilder clientBuilder = PulsarClient.builder() + .serviceUrl(config.getServiceAddr()); + + if (config.getAuthPlugin() != null) { + Preconditions.checkNotNull(config.getAuthParams(), + "Authentication Enabled in pulsar cluster, Please set authParams in pulsar-client.properties"); + clientBuilder.authentication( + config.getAuthPlugin(), + config.getAuthParams() + ); + } + + this.pulsarClient = clientBuilder.build(); + } catch (PulsarClientException ex) { + throw new ConnectorRuntimeException( + String.format("Failed to connect pulsar cluster %s with exception: %s", config.getServiceAddr(), ex.getMessage())); + } + } + + private Producer createProducer(String topic) { + try { + return this.pulsarClient.newProducer() + .topic(topic) + .batchingMaxPublishDelay(10, TimeUnit.MILLISECONDS) + .sendTimeout(10, TimeUnit.SECONDS) + .blockIfQueueFull(true) + .create(); + } catch (PulsarClientException ex) { + throw new ConnectorRuntimeException( + String.format("Failed to create pulsar producer for %s with exception: %s", topic, ex.getMessage())); + } + } + + public void publish(CloudEvent cloudEvent, SendCallback sendCallback) { + String topic = cloudEvent.getSubject(); + Producer producer = producerMap.computeIfAbsent(topic, k -> createProducer(topic)); + try { + byte[] serializedCloudEvent = EventFormatProvider + .getInstance() + .resolveFormat(JsonFormat.CONTENT_TYPE) + .serialize(cloudEvent); + producer.sendAsync(serializedCloudEvent).thenAccept(messageId -> { + sendCallback.onSuccess(CloudEventUtils.convertSendResult(cloudEvent)); + }); + } catch (Exception ex) { + log.error("Failed to publish cloudEvent for {} with exception: {}", + cloudEvent.getSubject(), ex.getMessage()); + } + } + + public void shutdown() throws PulsarClientException { + pulsarClient.close(); + for (Map.Entry> producerEntry : producerMap.entrySet()) { + producerEntry.getValue().close(); + } + producerMap.clear(); + } + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/common/EventMeshConstants.java b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/common/EventMeshConstants.java new file mode 100644 index 0000000000..9049608a96 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/common/EventMeshConstants.java @@ -0,0 +1,22 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pulsar.common; + +public class EventMeshConstants { + public static final String EVENTMESH_CONF_FILE = "pulsar-client.properties"; +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/config/ClientConfiguration.java b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/config/ClientConfiguration.java new file mode 100644 index 0000000000..ae0bc56267 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/config/ClientConfiguration.java @@ -0,0 +1,60 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pulsar.config; + +import org.apache.commons.lang3.StringUtils; + +import com.google.common.base.Preconditions; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ClientConfiguration { + + private String serviceAddr; + private String authPlugin; + private String authParams; + + private static ClientConfiguration INSTANCE = null; + + public void init() { + String serviceAddrStr = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_PULSAR_SERVICE_ADDR); + Preconditions.checkState(StringUtils.isNotEmpty(serviceAddrStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_PULSAR_SERVICE_ADDR)); + serviceAddr = StringUtils.trim(serviceAddrStr); + authPlugin = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_PULSAR_AUTH_PLUGIN); + authParams = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_PULSAR_AUTH_PARAMS); + } + + public static ClientConfiguration getInstance() { + if (INSTANCE == null) { + INSTANCE = new ClientConfiguration(); + INSTANCE.init(); + } + return INSTANCE; + } + + static class ConfKeys { + public static final String KEYS_EVENTMESH_PULSAR_SERVICE_ADDR = "eventMesh.server.pulsar.service"; + public static final String KEYS_EVENTMESH_PULSAR_AUTH_PLUGIN = "eventMesh.server.pulsar.authPlugin"; + public static final String KEYS_EVENTMESH_PULSAR_AUTH_PARAMS = "eventMesh.server.pulsar.authParams"; + } + +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/config/ConfigurationWrapper.java b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/config/ConfigurationWrapper.java new file mode 100644 index 0000000000..ca2ccd0aa6 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/config/ConfigurationWrapper.java @@ -0,0 +1,74 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pulsar.config; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.connector.pulsar.common.EventMeshConstants; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@UtilityClass +public class ConfigurationWrapper { + + private static final Properties properties = new Properties(); + + static { + loadProperties(); + } + + public String getProp(String key) { + return StringUtils.isEmpty(key) ? null : properties.getProperty(key, null); + } + + /** + * Load Pulsar properties file from classpath and conf home. + * The properties defined in conf home will override classpath. + */ + private void loadProperties() { + try (InputStream resourceAsStream = ConfigurationWrapper.class.getResourceAsStream( + "/" + EventMeshConstants.EVENTMESH_CONF_FILE)) { + if (resourceAsStream != null) { + properties.load(resourceAsStream); + } + } catch (IOException e) { + log.error("Load {}.properties file from classpath error", EventMeshConstants.EVENTMESH_CONF_FILE, e); + throw new RuntimeException(String.format("Load %s.properties file from classpath error", EventMeshConstants.EVENTMESH_CONF_FILE)); + } + + try { + String configPath = Constants.EVENTMESH_CONF_HOME + File.separator + EventMeshConstants.EVENTMESH_CONF_FILE; + if (new File(configPath).exists()) { + properties.load(new BufferedReader(new FileReader(configPath))); + } + } catch (IOException e) { + log.error("Cannot load {} file from conf.", EventMeshConstants.EVENTMESH_CONF_FILE, e); + throw new IllegalArgumentException(String.format("Cannot load %s file from conf", EventMeshConstants.EVENTMESH_CONF_FILE)); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/connector/ConnectorResourceServicePulsarImpl.java b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/connector/ConnectorResourceServicePulsarImpl.java new file mode 100644 index 0000000000..867feb2381 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/connector/ConnectorResourceServicePulsarImpl.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pulsar.connector; + +import org.apache.eventmesh.api.connector.ConnectorResourceService; + +public class ConnectorResourceServicePulsarImpl implements ConnectorResourceService { + @Override + public void init() throws Exception { + + } + + @Override + public void release() throws Exception { + + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/consumer/PulsarConsumerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/consumer/PulsarConsumerImpl.java new file mode 100644 index 0000000000..f2a621ab9c --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/consumer/PulsarConsumerImpl.java @@ -0,0 +1,163 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pulsar.consumer; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.api.EventMeshAsyncConsumeContext; +import org.apache.eventmesh.api.consumer.Consumer; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.connector.pulsar.config.ClientConfiguration; + +import org.apache.pulsar.client.api.ClientBuilder; +import org.apache.pulsar.client.api.MessageListener; +import org.apache.pulsar.client.api.PulsarClient; +import org.apache.pulsar.client.api.PulsarClientException; + +import java.util.List; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.format.EventDeserializationException; +import io.cloudevents.core.provider.EventFormatProvider; +import io.cloudevents.jackson.JsonFormat; + +import com.google.common.base.Preconditions; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PulsarConsumerImpl implements Consumer { + + private final AtomicBoolean started = new AtomicBoolean(false); + private Properties properties; + private PulsarClient pulsarClient; + private org.apache.pulsar.client.api.Consumer consumer; + private EventListener eventListener; + + @Override + public void init(Properties properties) throws Exception { + this.properties = properties; + + final ClientConfiguration clientConfiguration = ClientConfiguration.getInstance(); + + try { + ClientBuilder clientBuilder = PulsarClient.builder() + .serviceUrl(clientConfiguration.getServiceAddr()); + + if (clientConfiguration.getAuthPlugin() != null) { + Preconditions.checkNotNull(clientConfiguration.getAuthParams(), + "Authentication Enabled in pulsar cluster, Please set authParams in pulsar-client.properties"); + clientBuilder.authentication( + clientConfiguration.getAuthPlugin(), + clientConfiguration.getAuthParams() + ); + } + + this.pulsarClient = clientBuilder.build(); + } catch (Exception ex) { + throw new ConnectorRuntimeException( + String.format("Failed to connect pulsar with exception: %", ex.getMessage())); + } + } + + @Override + public void start() { + this.started.compareAndSet(false, true); + } + + @Override + public void subscribe(String topic) throws Exception { + + if (pulsarClient == null) { + throw new ConnectorRuntimeException( + String.format("Cann't find the pulsar client for topic: %s", topic)); + } + + EventMeshAsyncConsumeContext consumeContext = new EventMeshAsyncConsumeContext() { + @Override + public void commit(EventMeshAction action) { + log.debug("message action: {} for topic: {}", action.name(), topic); + } + }; + + consumer = pulsarClient.newConsumer() + .topic(topic) + .subscriptionName(properties.getProperty(Constants.CONSUMER_GROUP)) + .messageListener( + (MessageListener) (ackConsumer, msg) -> { + CloudEvent cloudEvent = EventFormatProvider + .getInstance() + .resolveFormat(JsonFormat.CONTENT_TYPE) + .deserialize(msg.getData()); + eventListener.consume(cloudEvent, consumeContext); + try { + ackConsumer.acknowledge(msg); + } catch (PulsarClientException ex) { + throw new ConnectorRuntimeException( + String.format("Failed to unsubscribe the topic:%s with exception: %s", topic, ex.getMessage())); + } catch (EventDeserializationException ex) { + log.warn("The Message isn't json format, with exception:{}", ex.getMessage()); + } + }).subscribe(); + } + + @Override + public void unsubscribe(String topic) { + try { + consumer.unsubscribe(); + } catch (PulsarClientException ex) { + throw new ConnectorRuntimeException( + String.format("Failed to unsubscribe the topic:%s with exception: %s", topic, ex.getMessage())); + } + } + + @Override + public void updateOffset(List cloudEvents, AbstractContext context) { + } + + @Override + public void registerEventListener(EventListener listener) { + this.eventListener = listener; + } + + @Override + public boolean isStarted() { + return this.started.get(); + } + + @Override + public boolean isClosed() { + return !this.isStarted(); + } + + @Override + public void shutdown() { + this.started.compareAndSet(true, false); + try { + this.consumer.close(); + this.pulsarClient.close(); + } catch (PulsarClientException ex) { + throw new ConnectorRuntimeException( + String.format("Failed to close the pulsar client with exception: %s", ex.getMessage())); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/producer/AbstractProducer.java b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/producer/AbstractProducer.java new file mode 100644 index 0000000000..f0e4858e83 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/producer/AbstractProducer.java @@ -0,0 +1,55 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pulsar.producer; + +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; + +import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; + + +import io.cloudevents.CloudEvent; + +public abstract class AbstractProducer { + + protected final AtomicBoolean started = new AtomicBoolean(false); + final Properties properties; + + AbstractProducer(final Properties properties) { + this.properties = properties; + } + + public Properties properties() { + return this.properties; + } + + ConnectorRuntimeException checkProducerException(CloudEvent cloudEvent, Throwable e) { + if (cloudEvent.getData() == null) { + return new ConnectorRuntimeException(String.format("CloudEvent message data does not exist, %s", e.getMessage())); + } + return new ConnectorRuntimeException(String.format("Unknown connector runtime exception, %s", e.getMessage())); + } + + public boolean isStarted() { + return this.started.get(); + } + + public boolean isClosed() { + return !this.isStarted(); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/producer/ProducerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/producer/ProducerImpl.java new file mode 100644 index 0000000000..e49ef3b39e --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/producer/ProducerImpl.java @@ -0,0 +1,76 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pulsar.producer; + +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.connector.pulsar.client.PulsarClientWrapper; +import org.apache.eventmesh.connector.pulsar.config.ClientConfiguration; + +import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; + +import io.cloudevents.CloudEvent; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ProducerImpl extends AbstractProducer { + + private final AtomicBoolean started = new AtomicBoolean(false); + + private ClientConfiguration config; + private PulsarClientWrapper pulsarClient; + + public ProducerImpl(final Properties properties) { + super(properties); + this.config = new ClientConfiguration(); + this.config.init(); + } + + public void publish(CloudEvent cloudEvent, SendCallback sendCallback) { + this.pulsarClient.publish(cloudEvent, sendCallback); + } + + public void init(Properties properties) { + new ProducerImpl(properties); + } + + public void start() { + this.started.compareAndSet(false, true); + this.pulsarClient = new PulsarClientWrapper(config); + } + + public void shutdown() { + try { + this.started.compareAndSet(true, false); + this.pulsarClient.shutdown(); + } catch (Exception ignored) { + // ignored + } + } + + @Override + public boolean isStarted() { + return this.started.get(); + } + + @Override + public boolean isClosed() { + return !this.isStarted(); + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/producer/PulsarProducerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/producer/PulsarProducerImpl.java new file mode 100644 index 0000000000..64c08847e0 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/producer/PulsarProducerImpl.java @@ -0,0 +1,87 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pulsar.producer; + +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.api.producer.Producer; + +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +public class PulsarProducerImpl implements Producer { + + private ProducerImpl producer; + + @Override + public synchronized void init(Properties properties) { + producer = new ProducerImpl(properties); + } + + @Override + public void publish(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + producer.publish(cloudEvent, sendCallback); + } + + @Override + public boolean isStarted() { + return producer.isStarted(); + } + + @Override + public boolean isClosed() { + return producer.isClosed(); + } + + @Override + public void start() { + producer.start(); + } + + @Override + public void shutdown() { + producer.shutdown(); + } + + @Override + public void sendOneway(CloudEvent cloudEvent) { + throw new ConnectorRuntimeException("SendOneWay is not supported"); + } + + @Override + public void request(CloudEvent cloudEvent, RequestReplyCallback rrCallback, long timeout) throws Exception { + throw new ConnectorRuntimeException("Request is not supported"); + } + + @Override + public boolean reply(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + throw new ConnectorRuntimeException("Reply is not supported"); + } + + @Override + public void checkTopicExist(String topic) throws Exception { + throw new ConnectorRuntimeException("CheckTopicExist is not supported"); + } + + @Override + public void setExtFields() { + throw new ConnectorRuntimeException("SetExtFields is not supported"); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/utils/CloudEventUtils.java b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/utils/CloudEventUtils.java new file mode 100644 index 0000000000..a02caf8996 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/java/org/apache/eventmesh/connector/pulsar/utils/CloudEventUtils.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.pulsar.utils; + +import org.apache.eventmesh.api.SendResult; + +import io.cloudevents.CloudEvent; + +public class CloudEventUtils { + public static SendResult convertSendResult(CloudEvent cloudEvent) { + SendResult sendResult = new SendResult(); + sendResult.setTopic(cloudEvent.getSubject()); + sendResult.setMessageId(cloudEvent.getId()); + return sendResult; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService new file mode 100644 index 0000000000..f4a99342e7 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService @@ -0,0 +1,16 @@ +# 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. + +pulsar=org.apache.eventmesh.connector.pulsar.connector.ConnectorResourceServicePulsarImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer new file mode 100644 index 0000000000..e835bc3cb1 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer @@ -0,0 +1,16 @@ +# 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. + +pulsar=org.apache.eventmesh.connector.pulsar.consumer.PulsarConsumerImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer new file mode 100644 index 0000000000..f8a5373ed0 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer @@ -0,0 +1,16 @@ +# 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. + +pulsar=org.apache.eventmesh.connector.pulsar.producer.PulsarProducerImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/resources/pulsar-client.properties b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/resources/pulsar-client.properties new file mode 100644 index 0000000000..cea69024e8 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-pulsar/src/main/resources/pulsar-client.properties @@ -0,0 +1,18 @@ +# +# 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. +# + +eventMesh.server.pulsar.service=127.0.0.1:6650 diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/build.gradle b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/build.gradle new file mode 100644 index 0000000000..5a691e3c56 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/build.gradle @@ -0,0 +1,48 @@ +/* + * 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. + */ + +configurations { + implementation.exclude group: 'ch.qos.logback', module: 'logback-classic' + implementation.exclude group: 'log4j', module: 'log4j' +} + +dependencies { + implementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + implementation project(":eventmesh-common") + // rabbitmq + implementation 'com.rabbitmq:amqp-client:5.16.0' + + testImplementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + testImplementation project(":eventmesh-common") + // rabbitmq + testImplementation 'com.rabbitmq:amqp-client:5.16.0' + + implementation 'io.cloudevents:cloudevents-json-jackson' + testImplementation 'io.cloudevents:cloudevents-json-jackson' + + testImplementation "org.mockito:mockito-core" + testImplementation "org.powermock:powermock-module-junit4" + testImplementation "org.powermock:powermock-api-mockito2" + + compileOnly 'org.projectlombok:lombok:1.18.22' + annotationProcessor 'org.projectlombok:lombok:1.18.22' + + testCompileOnly 'org.projectlombok:lombok:1.18.22' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.22' + + testImplementation('com.github.fridujo:rabbitmq-mock:1.1.1') +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/gradle.properties b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/gradle.properties new file mode 100644 index 0000000000..5df0ccda7b --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/gradle.properties @@ -0,0 +1,18 @@ +# 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. +# + +pluginType=connector +pluginName=rabbitmq \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/client/RabbitmqClient.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/client/RabbitmqClient.java new file mode 100644 index 0000000000..d4a2f128c2 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/client/RabbitmqClient.java @@ -0,0 +1,149 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.client; + +import org.apache.commons.lang3.StringUtils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.rabbitmq.client.BuiltinExchangeType; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +public class RabbitmqClient { + + private static final Logger logger = LoggerFactory.getLogger(RabbitmqClient.class); + + private final RabbitmqConnectionFactory rabbitmqConnectionFactory; + + public RabbitmqClient(RabbitmqConnectionFactory rabbitmqConnectionFactory) { + this.rabbitmqConnectionFactory = rabbitmqConnectionFactory; + } + + + /** + * get rabbitmq connection + * + * @param host host + * @param username username + * @param passwd password + * @param port port + * @param virtualHost virtual host + * @return connection + * @throws Exception Exception + */ + public Connection getConnection(String host, String username, + String passwd, int port, + String virtualHost) throws Exception { + ConnectionFactory factory = rabbitmqConnectionFactory.createConnectionFactory(); + factory.setHost(host.trim()); + factory.setPort(port); + if (StringUtils.isNotEmpty(virtualHost)) { + factory.setVirtualHost(virtualHost.trim()); + } + factory.setUsername(username); + factory.setPassword(passwd.trim()); + + return rabbitmqConnectionFactory.createConnection(factory); + } + + /** + * send message + * + * @param channel channel + * @param exchangeName exchange name + * @param routingKey routing key + * @param message message + * @throws Exception Exception + */ + public void publish(Channel channel, String exchangeName, + String routingKey, byte[] message) throws Exception { + channel.basicPublish(exchangeName, routingKey, null, message); + } + + /** + * binding queue + * + * @param channel channel + * @param builtinExchangeType exchange type + * @param exchangeName exchange name + * @param routingKey routing key + * @param queueName queue name + */ + public void binding(Channel channel, BuiltinExchangeType builtinExchangeType, + String exchangeName, String routingKey, String queueName) { + try { + channel.exchangeDeclare(exchangeName, builtinExchangeType.getType(), true, + false, false, null); + channel.queueDeclare(queueName, false, false, + false, null); + routingKey = builtinExchangeType.getType().equals(BuiltinExchangeType.FANOUT.getType()) ? "" : routingKey; + channel.queueBind(queueName, exchangeName, routingKey); + } catch (Exception ex) { + logger.error("[RabbitmqClient] binding happen exception.", ex); + } + } + + /** + * unbinding queue + * + * @param channel channel + * @param exchangeName exchange name + * @param routingKey routing key + * @param queueName queue name + */ + public void unbinding(Channel channel, String exchangeName, String routingKey, String queueName) { + try { + channel.queueUnbind(queueName, exchangeName, routingKey); + } catch (Exception ex) { + logger.error("[RabbitmqClient] unbinding happen exception.", ex); + } + } + + /** + * close connection + * + * @param connection connection + */ + public void closeConnection(Connection connection) { + if (null != connection) { + try { + connection.close(); + } catch (Exception ex) { + logger.error("[RabbitmqClient] connection close happen exception.", ex); + } + } + } + + /** + * close channel + * + * @param channel channel + */ + public void closeChannel(Channel channel) { + if (null != channel) { + try { + channel.close(); + } catch (Exception ex) { + logger.error("[RabbitmqClient] channel close happen exception.", ex); + } + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/client/RabbitmqConnectionFactory.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/client/RabbitmqConnectionFactory.java new file mode 100644 index 0000000000..2ff41f4f90 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/client/RabbitmqConnectionFactory.java @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.client; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +public class RabbitmqConnectionFactory { + + public ConnectionFactory createConnectionFactory() { + return new ConnectionFactory(); + } + + public Connection createConnection(ConnectionFactory connectionFactory) throws IOException, TimeoutException { + return connectionFactory.newConnection(); + } + + public Channel createChannel(Connection connection) throws IOException { + return connection.createChannel(); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/cloudevent/RabbitmqCloudEvent.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/cloudevent/RabbitmqCloudEvent.java new file mode 100644 index 0000000000..d0c762ac54 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/cloudevent/RabbitmqCloudEvent.java @@ -0,0 +1,77 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.cloudevent; + +import org.apache.eventmesh.connector.rabbitmq.exception.RabbitmqaConnectorException; +import org.apache.eventmesh.connector.rabbitmq.utils.ByteArrayUtils; + +import java.io.Serializable; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import io.cloudevents.CloudEvent; +import io.cloudevents.SpecVersion; +import io.cloudevents.core.builder.CloudEventBuilder; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class RabbitmqCloudEvent implements Serializable { + + private SpecVersion version; + private String data; + private Map extensions = new HashMap<>(); + + public CloudEvent convertToCloudEvent() { + CloudEventBuilder builder; + switch (version) { + case V03: + builder = CloudEventBuilder.v03(); + break; + case V1: + builder = CloudEventBuilder.v1(); + break; + default: + throw new RabbitmqaConnectorException(String.format("CloudEvent version %s does not support.", version)); + } + builder.withData(data.getBytes(StandardCharsets.UTF_8)) + .withId(extensions.remove("id")) + .withSource(URI.create(extensions.remove("source"))) + .withType(extensions.remove("type")) + .withDataContentType(extensions.remove("datacontenttype")) + .withSubject(extensions.remove("subject")); + extensions.forEach(builder::withExtension); + + return builder.build(); + } + + public static byte[] toByteArray(RabbitmqCloudEvent rabbitmqCloudEvent) throws Exception { + Optional optionalBytes = ByteArrayUtils.objectToBytes(rabbitmqCloudEvent); + return optionalBytes.orElseGet(() -> new byte[]{}); + } + + public static RabbitmqCloudEvent getFromByteArray(byte[] body) throws Exception { + Optional optionalCloudEvent = ByteArrayUtils.bytesToObject(body); + return optionalCloudEvent.orElse(null); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/cloudevent/RabbitmqCloudEventWriter.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/cloudevent/RabbitmqCloudEventWriter.java new file mode 100644 index 0000000000..b7e2e093f1 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/cloudevent/RabbitmqCloudEventWriter.java @@ -0,0 +1,68 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.cloudevent; + +import java.nio.charset.StandardCharsets; + +import io.cloudevents.CloudEventData; +import io.cloudevents.SpecVersion; +import io.cloudevents.core.format.EventFormat; +import io.cloudevents.core.message.MessageWriter; +import io.cloudevents.rw.CloudEventContextWriter; +import io.cloudevents.rw.CloudEventRWException; +import io.cloudevents.rw.CloudEventWriter; + +public class RabbitmqCloudEventWriter + implements MessageWriter, RabbitmqCloudEvent>, CloudEventWriter { + + private final RabbitmqCloudEvent rabbitmqCloudEvent; + + public RabbitmqCloudEventWriter() { + rabbitmqCloudEvent = new RabbitmqCloudEvent(); + } + + @Override + public RabbitmqCloudEvent setEvent(EventFormat format, byte[] value) throws CloudEventRWException { + rabbitmqCloudEvent.setData(new String(value, StandardCharsets.UTF_8)); + return rabbitmqCloudEvent; + } + + @Override + public RabbitmqCloudEvent end(CloudEventData data) throws CloudEventRWException { + rabbitmqCloudEvent.setData(new String(data.toBytes(), StandardCharsets.UTF_8)); + return rabbitmqCloudEvent; + } + + @Override + public RabbitmqCloudEvent end() throws CloudEventRWException { + rabbitmqCloudEvent.setData(""); + return rabbitmqCloudEvent; + } + + @Override + public CloudEventContextWriter withContextAttribute(String name, String value) throws CloudEventRWException { + rabbitmqCloudEvent.getExtensions().put(name, value); + return this; + } + + @Override + public CloudEventWriter create(SpecVersion version) throws CloudEventRWException { + rabbitmqCloudEvent.setVersion(version); + return this; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/config/ConfigKey.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/config/ConfigKey.java new file mode 100644 index 0000000000..9173e5ffc6 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/config/ConfigKey.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.config; + +public class ConfigKey { + public static final String HOST = "eventMesh.server.rabbitmq.host"; + public static final String PORT = "eventMesh.server.rabbitmq.port"; + public static final String USER_NAME = "eventMesh.server.rabbitmq.username"; + public static final String PASSWD = "eventMesh.server.rabbitmq.passwd"; + public static final String VIRTUAL_HOST = "eventMesh.server.rabbitmq.virtualHost"; + + public static final String EXCHANGE_TYPE = "eventMesh.server.rabbitmq.exchangeType"; + public static final String EXCHANGE_NAME = "eventMesh.server.rabbitmq.exchangeName"; + public static final String ROUTING_KEY = "eventMesh.server.rabbitmq.routingKey"; + public static final String QUEUE_NAME = "eventMesh.server.rabbitmq.queueName"; + public static final String AUTO_ACK = "eventMesh.server.rabbitmq.autoAck"; +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/config/ConfigurationHolder.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/config/ConfigurationHolder.java new file mode 100644 index 0000000000..34a7e71895 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/config/ConfigurationHolder.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.config; + +import org.apache.eventmesh.common.utils.AssertUtils; + +import com.rabbitmq.client.BuiltinExchangeType; + +import lombok.Data; + +@Data +public class ConfigurationHolder { + public String host; + public int port; + public String username; + public String passwd; + public String virtualHost; + + public BuiltinExchangeType exchangeType; + public String exchangeName; + public String routingKey; + public String queueName; + public boolean autoAck; + + public void init() { + this.host = getProperty(ConfigKey.HOST); + this.port = Integer.parseInt(getProperty(ConfigKey.PORT)); + this.username = getProperty(ConfigKey.USER_NAME); + this.passwd = getProperty(ConfigKey.PASSWD); + this.virtualHost = ConfigurationWrapper.getProperty(ConfigKey.VIRTUAL_HOST); + this.exchangeType = BuiltinExchangeType.valueOf(getProperty(ConfigKey.EXCHANGE_TYPE)); + this.exchangeName = getProperty(ConfigKey.EXCHANGE_NAME); + this.routingKey = getProperty(ConfigKey.ROUTING_KEY); + this.queueName = getProperty(ConfigKey.QUEUE_NAME); + this.autoAck = Boolean.parseBoolean(getProperty(ConfigKey.AUTO_ACK)); + } + + /** + * get property + * + * @param configKey config key + * @return property + */ + private String getProperty(String configKey) { + String property = ConfigurationWrapper.getProperty(configKey); + AssertUtils.notBlack(property, String.format("%s error", configKey)); + return property; + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/config/ConfigurationWrapper.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/config/ConfigurationWrapper.java new file mode 100644 index 0000000000..6a244977fa --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/config/ConfigurationWrapper.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.config; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.utils.PropertiesUtils; + +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Properties; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ConfigurationWrapper { + + private static final String CONF_FILE = "rabbitmq-client.properties"; + + private static final Properties PROPERTIES = new Properties(); + + static { + loadProperties(); + } + + public static String getProperty(String key) { + return StringUtils.isEmpty(key) + ? null : PROPERTIES.getProperty(key, null); + } + + private static void loadProperties() { + try (InputStream resourceAsStream = ConfigurationWrapper.class.getResourceAsStream( + "/" + CONF_FILE)) { + if (resourceAsStream != null) { + PROPERTIES.load(resourceAsStream); + } + } catch (IOException e) { + log.error("load file from classpath exception:", e); + throw new RuntimeException(String.format("Load %s file from classpath error", CONF_FILE)); + } + try { + String configPath = Constants.EVENTMESH_CONF_HOME + File.separator + CONF_FILE; + PropertiesUtils.loadPropertiesWhenFileExist(PROPERTIES, configPath, StandardCharsets.UTF_8); + } catch (IOException e) { + log.error("load file from conf exception:", e); + throw new IllegalArgumentException(String.format("Cannot load %s file from conf", CONF_FILE)); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/connector/RabbitmqConnectorResourceService.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/connector/RabbitmqConnectorResourceService.java new file mode 100644 index 0000000000..2e16e613a5 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/connector/RabbitmqConnectorResourceService.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.connector; + +import org.apache.eventmesh.api.connector.ConnectorResourceService; + +public class RabbitmqConnectorResourceService implements ConnectorResourceService { + @Override + public void init() throws Exception { + + } + + @Override + public void release() throws Exception { + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/consumer/RabbitmqConsumer.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/consumer/RabbitmqConsumer.java new file mode 100644 index 0000000000..56124ab824 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/consumer/RabbitmqConsumer.java @@ -0,0 +1,134 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.consumer; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.consumer.Consumer; +import org.apache.eventmesh.common.ThreadPoolFactory; +import org.apache.eventmesh.connector.rabbitmq.client.RabbitmqClient; +import org.apache.eventmesh.connector.rabbitmq.client.RabbitmqConnectionFactory; +import org.apache.eventmesh.connector.rabbitmq.config.ConfigurationHolder; + +import java.util.List; +import java.util.Properties; +import java.util.concurrent.ThreadPoolExecutor; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; + +public class RabbitmqConsumer implements Consumer { + + private static final Logger logger = LoggerFactory.getLogger(RabbitmqConsumer.class); + + private RabbitmqConnectionFactory rabbitmqConnectionFactory = new RabbitmqConnectionFactory(); + + private RabbitmqClient rabbitmqClient; + + private Connection connection; + + private Channel channel; + + private volatile boolean started = false; + + private final ConfigurationHolder configurationHolder = new ConfigurationHolder(); + + private final ThreadPoolExecutor executor = ThreadPoolFactory.createThreadPoolExecutor( + Runtime.getRuntime().availableProcessors() * 2, + Runtime.getRuntime().availableProcessors() * 2, + "EventMesh-Rabbitmq-Consumer-"); + + private RabbitmqConsumerHandler rabbitmqConsumerHandler; + + @Override + public boolean isStarted() { + return started; + } + + @Override + public boolean isClosed() { + return !isStarted(); + } + + @Override + public void start() { + if (!started) { + started = true; + } + } + + @Override + public void shutdown() { + if (started) { + try { + rabbitmqClient.closeConnection(connection); + rabbitmqClient.closeChannel(channel); + rabbitmqConsumerHandler.stop(); + } finally { + started = false; + } + } + } + + @Override + public void init(Properties keyValue) throws Exception { + this.configurationHolder.init(); + this.rabbitmqClient = new RabbitmqClient(rabbitmqConnectionFactory); + this.connection = rabbitmqClient.getConnection(configurationHolder.getHost(), configurationHolder.getUsername(), + configurationHolder.getPasswd(), configurationHolder.getPort(), configurationHolder.getVirtualHost()); + this.channel = rabbitmqConnectionFactory.createChannel(connection); + this.rabbitmqConsumerHandler = new RabbitmqConsumerHandler(channel, configurationHolder); + } + + @Override + public void updateOffset(List cloudEvents, AbstractContext context) { + + } + + @Override + public void subscribe(String topic) { + rabbitmqClient.binding(channel, configurationHolder.getExchangeType(), configurationHolder.getExchangeName(), + configurationHolder.getRoutingKey(), configurationHolder.getQueueName()); + executor.execute(rabbitmqConsumerHandler); + } + + @Override + public void unsubscribe(String topic) { + try { + rabbitmqClient.unbinding(channel, configurationHolder.getExchangeName(), + configurationHolder.getRoutingKey(), configurationHolder.getQueueName()); + rabbitmqConsumerHandler.stop(); + } catch (Exception ex) { + logger.error("[RabbitmqConsumer] unsubscribe happen exception.", ex); + } + } + + @Override + public void registerEventListener(EventListener listener) { + rabbitmqConsumerHandler.setEventListener(listener); + } + + public void setRabbitmqConnectionFactory(RabbitmqConnectionFactory rabbitmqConnectionFactory) { + this.rabbitmqConnectionFactory = rabbitmqConnectionFactory; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/consumer/RabbitmqConsumerHandler.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/consumer/RabbitmqConsumerHandler.java new file mode 100644 index 0000000000..0d53bb1b3e --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/consumer/RabbitmqConsumerHandler.java @@ -0,0 +1,84 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.consumer; + +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.api.EventMeshAsyncConsumeContext; +import org.apache.eventmesh.connector.rabbitmq.cloudevent.RabbitmqCloudEvent; +import org.apache.eventmesh.connector.rabbitmq.config.ConfigurationHolder; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.GetResponse; + +public class RabbitmqConsumerHandler implements Runnable { + + private static final Logger logger = LoggerFactory.getLogger(RabbitmqConsumerHandler.class); + + private final Channel channel; + private final ConfigurationHolder configurationHolder; + private final AtomicBoolean stop = new AtomicBoolean(false); + private EventListener eventListener; + + public RabbitmqConsumerHandler(Channel channel, ConfigurationHolder configurationHolder) { + this.channel = channel; + this.configurationHolder = configurationHolder; + } + + @Override + public void run() { + while (!stop.get()) { + try { + GetResponse response = channel.basicGet(configurationHolder.getQueueName(), configurationHolder.isAutoAck()); + if (response != null) { + RabbitmqCloudEvent rabbitmqCloudEvent = RabbitmqCloudEvent.getFromByteArray(response.getBody()); + CloudEvent cloudEvent = rabbitmqCloudEvent.convertToCloudEvent(); + final EventMeshAsyncConsumeContext consumeContext = new EventMeshAsyncConsumeContext() { + @Override + public void commit(EventMeshAction action) { + logger.info("[RabbitmqConsumerHandler] Rabbitmq consumer context commit."); + } + }; + if (eventListener != null) { + eventListener.consume(cloudEvent, consumeContext); + } + if (!configurationHolder.isAutoAck()) { + channel.basicAck(response.getEnvelope().getDeliveryTag(), false); + } + } + } catch (Exception ex) { + logger.error("[RabbitmqConsumerHandler] thread run happen exception.", ex); + } + } + } + + public void setEventListener(EventListener eventListener) { + this.eventListener = eventListener; + } + + public void stop() { + stop.set(true); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/exception/RabbitmqaConnectorException.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/exception/RabbitmqaConnectorException.java new file mode 100644 index 0000000000..ba06999804 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/exception/RabbitmqaConnectorException.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.exception; + +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; + +public class RabbitmqaConnectorException extends ConnectorRuntimeException { + + public RabbitmqaConnectorException(String message) { + super(message); + } + + public RabbitmqaConnectorException(Throwable throwable) { + super(throwable); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/producer/RabbitmqProducer.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/producer/RabbitmqProducer.java new file mode 100644 index 0000000000..700c44792d --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/producer/RabbitmqProducer.java @@ -0,0 +1,161 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.producer; + +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.api.exception.OnExceptionContext; +import org.apache.eventmesh.api.producer.Producer; +import org.apache.eventmesh.connector.rabbitmq.client.RabbitmqClient; +import org.apache.eventmesh.connector.rabbitmq.client.RabbitmqConnectionFactory; +import org.apache.eventmesh.connector.rabbitmq.cloudevent.RabbitmqCloudEvent; +import org.apache.eventmesh.connector.rabbitmq.cloudevent.RabbitmqCloudEventWriter; +import org.apache.eventmesh.connector.rabbitmq.config.ConfigurationHolder; +import org.apache.eventmesh.connector.rabbitmq.utils.ByteArrayUtils; + +import java.util.Optional; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; + +public class RabbitmqProducer implements Producer { + + private static final Logger logger = LoggerFactory.getLogger(RabbitmqProducer.class); + + private RabbitmqConnectionFactory rabbitmqConnectionFactory = new RabbitmqConnectionFactory(); + + private RabbitmqClient rabbitmqClient; + + private Connection connection; + + private Channel channel; + + private volatile boolean started = false; + + private final ConfigurationHolder configurationHolder = new ConfigurationHolder(); + + @Override + public boolean isStarted() { + return started; + } + + @Override + public boolean isClosed() { + return !isStarted(); + } + + @Override + public void start() { + if (!started) { + started = true; + } + } + + @Override + public void shutdown() { + if (started) { + try { + rabbitmqClient.closeConnection(connection); + rabbitmqClient.closeChannel(channel); + } finally { + started = false; + } + } + } + + @Override + public void init(Properties properties) throws Exception { + this.configurationHolder.init(); + this.rabbitmqClient = new RabbitmqClient(rabbitmqConnectionFactory); + this.connection = rabbitmqClient.getConnection(configurationHolder.getHost(), configurationHolder.getUsername(), + configurationHolder.getPasswd(), configurationHolder.getPort(), configurationHolder.getVirtualHost()); + this.channel = rabbitmqConnectionFactory.createChannel(connection); + } + + @Override + public void publish(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + try { + RabbitmqCloudEventWriter writer = new RabbitmqCloudEventWriter(); + RabbitmqCloudEvent rabbitmqCloudEvent = writer.writeBinary(cloudEvent); + byte[] data = RabbitmqCloudEvent.toByteArray(rabbitmqCloudEvent); + if (data != null) { + rabbitmqClient.publish(channel, configurationHolder.getExchangeName(), configurationHolder.getRoutingKey(), data); + + SendResult sendResult = new SendResult(); + sendResult.setTopic(cloudEvent.getSubject()); + sendResult.setMessageId(cloudEvent.getId()); + sendCallback.onSuccess(sendResult); + } + } catch (Exception ex) { + logger.error("[RabbitmqProducer] publish happen exception.", ex); + sendCallback.onException( + OnExceptionContext.builder() + .topic(cloudEvent.getSubject()) + .messageId(cloudEvent.getId()) + .exception(new ConnectorRuntimeException(ex)) + .build() + ); + } + } + + @Override + public void sendOneway(CloudEvent cloudEvent) { + try { + Optional optionalBytes = ByteArrayUtils.objectToBytes(cloudEvent); + if (optionalBytes.isPresent()) { + byte[] data = optionalBytes.get(); + rabbitmqClient.publish(channel, configurationHolder.getExchangeName(), + configurationHolder.getRoutingKey(), data); + } + } catch (Exception ex) { + logger.error("[RabbitmqProducer] sendOneway happen exception.", ex); + } + } + + @Override + public void request(CloudEvent cloudEvent, RequestReplyCallback rrCallback, long timeout) throws Exception { + + } + + @Override + public boolean reply(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + return false; + } + + @Override + public void checkTopicExist(String topic) throws Exception { + + } + + @Override + public void setExtFields() { + + } + + public void setRabbitmqConnectionFactory(RabbitmqConnectionFactory rabbitmqConnectionFactory) { + this.rabbitmqConnectionFactory = rabbitmqConnectionFactory; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/utils/ByteArrayUtils.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/utils/ByteArrayUtils.java new file mode 100644 index 0000000000..5554d459f4 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/java/org/apache/eventmesh/connector/rabbitmq/utils/ByteArrayUtils.java @@ -0,0 +1,49 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.utils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Optional; + +@SuppressWarnings("all") +public class ByteArrayUtils { + + public static Optional objectToBytes(T obj) throws IOException { + byte[] bytes = null; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream sOut = new ObjectOutputStream(out); + sOut.writeObject(obj); + sOut.flush(); + bytes = out.toByteArray(); + + return Optional.ofNullable(bytes); + } + + public static Optional bytesToObject(byte[] bytes) throws IOException, ClassNotFoundException { + T t = null; + ByteArrayInputStream in = new ByteArrayInputStream(bytes); + ObjectInputStream sIn = new ObjectInputStream(in); + t = (T) sIn.readObject(); + return Optional.ofNullable(t); + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService new file mode 100644 index 0000000000..1b7228c7cb --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService @@ -0,0 +1,16 @@ +# 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. + +rabbitmq=org.apache.eventmesh.connector.rabbitmq.connector.RabbitmqConnectorResourceService \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer new file mode 100644 index 0000000000..1d9791e92d --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer @@ -0,0 +1,16 @@ +# 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. + +rabbitmq=org.apache.eventmesh.connector.rabbitmq.consumer.RabbitmqConsumer \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer new file mode 100644 index 0000000000..d60ea94bb4 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer @@ -0,0 +1,16 @@ +# 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. + +rabbitmq=org.apache.eventmesh.connector.rabbitmq.producer.RabbitmqProducer \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/resources/rabbitmq-client.properties b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/resources/rabbitmq-client.properties new file mode 100644 index 0000000000..db9f3a5fa8 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/main/resources/rabbitmq-client.properties @@ -0,0 +1,31 @@ +# +# 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. +# + +####################### rabbitmq server ################## +eventMesh.server.rabbitmq.host= +eventMesh.server.rabbitmq.port= +eventMesh.server.rabbitmq.username= +eventMesh.server.rabbitmq.passwd= +eventMesh.server.rabbitmq.virtualHost= + +####################### rabbitmq queue setting ################## +# DIRECT, FANOUT, TOPIC, HEADERS +eventMesh.server.rabbitmq.exchangeType=TOPIC +eventMesh.server.rabbitmq.exchangeName= +eventMesh.server.rabbitmq.routingKey= +eventMesh.server.rabbitmq.queueName= +eventMesh.server.rabbitmq.autoAck=true \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/RabbitmqMockConnectionFactory.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/RabbitmqMockConnectionFactory.java new file mode 100644 index 0000000000..912e825bf0 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/RabbitmqMockConnectionFactory.java @@ -0,0 +1,59 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq; + +import org.apache.eventmesh.connector.rabbitmq.client.RabbitmqConnectionFactory; + +import com.github.fridujo.rabbitmq.mock.MockConnectionFactory; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +public class RabbitmqMockConnectionFactory extends RabbitmqConnectionFactory { + + private final ConnectionFactory myConnectionFactory; + + private final Connection myConnection; + + private final Channel myChannel; + + public RabbitmqMockConnectionFactory() throws Exception { + this.myConnectionFactory = new MockConnectionFactory(); + this.myConnectionFactory.setHost("127.0.0.1"); + this.myConnectionFactory.setPort(5672); + this.myConnectionFactory.setUsername("root"); + this.myConnectionFactory.setPassword("123456"); + this.myConnection = this.myConnectionFactory.newConnection(); + this.myChannel = myConnection.createChannel(); + } + + @Override + public ConnectionFactory createConnectionFactory() { + return this.myConnectionFactory; + } + + @Override + public Connection createConnection(ConnectionFactory connectionFactory) { + return this.myConnection; + } + + @Override + public Channel createChannel(Connection connection) { + return this.myChannel; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/RabbitmqServer.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/RabbitmqServer.java new file mode 100644 index 0000000000..a6287339d9 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/RabbitmqServer.java @@ -0,0 +1,52 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq; + +import org.apache.eventmesh.connector.rabbitmq.consumer.RabbitmqConsumer; +import org.apache.eventmesh.connector.rabbitmq.producer.RabbitmqProducer; + +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; + +public class RabbitmqServer { + protected RabbitmqConsumer rabbitmqConsumer; + protected RabbitmqProducer rabbitmqProducer; + + @Before + public void setup() throws Exception { + RabbitmqMockConnectionFactory rabbitmqMockConnectionFactory = new RabbitmqMockConnectionFactory(); + + rabbitmqConsumer = new RabbitmqConsumer(); + rabbitmqConsumer.setRabbitmqConnectionFactory(rabbitmqMockConnectionFactory); + rabbitmqConsumer.init(new Properties()); + rabbitmqConsumer.start(); + + rabbitmqProducer = new RabbitmqProducer(); + rabbitmqProducer.setRabbitmqConnectionFactory(rabbitmqMockConnectionFactory); + rabbitmqProducer.init(new Properties()); + rabbitmqProducer.start(); + } + + @After + public void shutdown() { + rabbitmqConsumer.shutdown(); + rabbitmqProducer.shutdown(); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/cloudevent/RabbitmqCloudEventTest.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/cloudevent/RabbitmqCloudEventTest.java new file mode 100644 index 0000000000..687a399ebd --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/cloudevent/RabbitmqCloudEventTest.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.cloudevent; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.time.OffsetDateTime; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; + +public class RabbitmqCloudEventTest { + + private CloudEvent cloudEvent; + + @Before + public void before() { + cloudEvent = CloudEventBuilder.v1() + .withId("1") + .withTime(OffsetDateTime.now()) + .withSource(URI.create("testsource")) + .withSubject("topic") + .withType(String.class.getCanonicalName()) + .withDataContentType("text/plain") + .withData("data".getBytes(StandardCharsets.UTF_8)) + .build(); + } + + @Test + public void toByteArray() throws Exception { + RabbitmqCloudEventWriter writer = new RabbitmqCloudEventWriter(); + RabbitmqCloudEvent rabbitmqCloudEvent = writer.writeBinary(cloudEvent); + Assert.assertEquals(cloudEvent.getSubject(), "topic"); + + byte[] data = RabbitmqCloudEvent.toByteArray(rabbitmqCloudEvent); + Assert.assertNotNull(data); + } + + @Test + public void getFromByteArray() throws Exception { + RabbitmqCloudEventWriter writer = new RabbitmqCloudEventWriter(); + RabbitmqCloudEvent rabbitmqCloudEvent = writer.writeBinary(cloudEvent); + Assert.assertEquals(cloudEvent.getSubject(), "topic"); + + byte[] data = RabbitmqCloudEvent.toByteArray(rabbitmqCloudEvent); + Assert.assertNotNull(data); + + RabbitmqCloudEvent event = RabbitmqCloudEvent.getFromByteArray(data); + Assert.assertEquals(event.getExtensions().get("subject"), "topic"); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/consumer/RabbitmqConsumerTest.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/consumer/RabbitmqConsumerTest.java new file mode 100644 index 0000000000..1e5a3969a6 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/consumer/RabbitmqConsumerTest.java @@ -0,0 +1,92 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.consumer; + +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.api.exception.OnExceptionContext; +import org.apache.eventmesh.connector.rabbitmq.RabbitmqServer; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.time.OffsetDateTime; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.junit.Assert; +import org.junit.Test; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; + +public class RabbitmqConsumerTest extends RabbitmqServer { + + @Test + public void isStarted() { + Assert.assertTrue(rabbitmqConsumer.isStarted()); + } + + @Test + public void isClosed() { + Assert.assertFalse(rabbitmqConsumer.isClosed()); + } + + @Test + public void subscribe() throws Exception { + final int expectedCount = 5; + final CountDownLatch downLatch = new CountDownLatch(expectedCount); + + rabbitmqConsumer.registerEventListener((cloudEvent, context) -> { + downLatch.countDown(); + context.commit(EventMeshAction.CommitMessage); + Assert.assertEquals(cloudEvent.getSubject(), "topic"); + }); + + rabbitmqConsumer.subscribe("topic"); + + Thread.sleep(1000); + for (int i = 0; i < expectedCount; i++) { + CloudEvent cloudEvent = CloudEventBuilder.v1() + .withId(String.valueOf(i)) + .withTime(OffsetDateTime.now()) + .withSource(URI.create("testsource")) + .withSubject("topic") + .withType(String.class.getCanonicalName()) + .withDataContentType("text/plain") + .withData("data".getBytes(StandardCharsets.UTF_8)) + .build(); + + rabbitmqProducer.publish(cloudEvent, new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + Assert.assertEquals(cloudEvent.getId(), sendResult.getMessageId()); + Assert.assertEquals(cloudEvent.getSubject(), sendResult.getTopic()); + } + + @Override + public void onException(OnExceptionContext context) { + Assert.assertEquals(cloudEvent.getId(), context.getMessageId()); + Assert.assertEquals(cloudEvent.getSubject(), context.getTopic()); + } + }); + } + + Assert.assertTrue(downLatch.await(5, TimeUnit.MINUTES)); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/producer/RabbitmqProducerTest.java b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/producer/RabbitmqProducerTest.java new file mode 100644 index 0000000000..bf39e2cc52 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/java/org/apache/eventmesh/connector/rabbitmq/producer/RabbitmqProducerTest.java @@ -0,0 +1,92 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rabbitmq.producer; + +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.api.exception.OnExceptionContext; +import org.apache.eventmesh.connector.rabbitmq.RabbitmqServer; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.time.OffsetDateTime; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.junit.Assert; +import org.junit.Test; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; + +public class RabbitmqProducerTest extends RabbitmqServer { + + @Test + public void isStarted() { + Assert.assertTrue(rabbitmqProducer.isStarted()); + } + + @Test + public void isClosed() { + Assert.assertFalse(rabbitmqProducer.isClosed()); + } + + @Test + public void publish() throws Exception { + final int expectedCount = 5; + final CountDownLatch downLatch = new CountDownLatch(expectedCount); + + rabbitmqConsumer.registerEventListener((cloudEvent, context) -> { + downLatch.countDown(); + context.commit(EventMeshAction.CommitMessage); + Assert.assertEquals(cloudEvent.getSubject(), "topic"); + }); + + rabbitmqConsumer.subscribe("topic"); + + Thread.sleep(1000); + for (int i = 0; i < expectedCount; i++) { + CloudEvent cloudEvent = CloudEventBuilder.v1() + .withId(String.valueOf(i)) + .withTime(OffsetDateTime.now()) + .withSource(URI.create("testsource")) + .withSubject("topic") + .withType(String.class.getCanonicalName()) + .withDataContentType("text/plain") + .withData("data".getBytes(StandardCharsets.UTF_8)) + .build(); + + rabbitmqProducer.publish(cloudEvent, new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + Assert.assertEquals(cloudEvent.getId(), sendResult.getMessageId()); + Assert.assertEquals(cloudEvent.getSubject(), sendResult.getTopic()); + } + + @Override + public void onException(OnExceptionContext context) { + Assert.assertEquals(cloudEvent.getId(), context.getMessageId()); + Assert.assertEquals(cloudEvent.getSubject(), context.getTopic()); + } + }); + } + + Assert.assertTrue(downLatch.await(5, TimeUnit.MINUTES)); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/resources/rabbitmq-client.properties b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/resources/rabbitmq-client.properties new file mode 100644 index 0000000000..b24967fa6c --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rabbitmq/src/test/resources/rabbitmq-client.properties @@ -0,0 +1,31 @@ +# +# 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. +# + +####################### rabbitmq server ################## +eventMesh.server.rabbitmq.host=127.0.0.1 +eventMesh.server.rabbitmq.port=5672 +eventMesh.server.rabbitmq.username=root +eventMesh.server.rabbitmq.passwd=123456 +eventMesh.server.rabbitmq.virtualHost=test + +####################### rabbitmq queue setting ################## +# DIRECT, FANOUT, TOPIC, HEADERS +eventMesh.server.rabbitmq.exchangeType=TOPIC +eventMesh.server.rabbitmq.exchangeName=test +eventMesh.server.rabbitmq.routingKey=test +eventMesh.server.rabbitmq.queueName=test +eventMesh.server.rabbitmq.autoAck=true \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/build.gradle b/eventmesh-connector-plugin/eventmesh-connector-redis/build.gradle new file mode 100644 index 0000000000..9ba6898dbd --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/build.gradle @@ -0,0 +1,56 @@ +/* + * 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. + */ + +configurations { + implementation.exclude group: 'org.slf4j', module: 'slf4j-simple' +} + +dependencies { + implementation project(":eventmesh-common") + implementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + + // redisson + implementation('org.redisson:redisson:3.17.3') { + exclude group: 'io.netty', module: 'netty-common' + exclude group: 'io.netty', module: 'netty-buffer' + exclude group: 'io.netty', module: 'netty-codec' + exclude group: 'io.netty', module: 'netty-transport' + exclude group: 'io.netty', module: 'netty-resolver' + exclude group: 'io.netty', module: 'netty-resolver-dns' + exclude group: 'io.netty', module: 'netty-handler' + } + + // netty + implementation "io.netty:netty-all" + + // auxiliary serialize + api 'io.cloudevents:cloudevents-json-jackson' + + // test dependencies + testImplementation 'ai.grakn:redis-mock:0.1.6' + testImplementation "org.mockito:mockito-core" + + compileOnly 'org.projectlombok:lombok:1.18.22' + annotationProcessor 'org.projectlombok:lombok:1.18.22' + + testCompileOnly 'org.projectlombok:lombok:1.18.22' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.22' +} + +test { + systemProperty "io.netty.tryUnsafe", "false" +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/gradle.properties b/eventmesh-connector-plugin/eventmesh-connector-redis/gradle.properties new file mode 100644 index 0000000000..f99be9b880 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/gradle.properties @@ -0,0 +1,18 @@ +# 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. +# + +pluginType=connector +pluginName=redis \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/client/RedissonClient.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/client/RedissonClient.java new file mode 100644 index 0000000000..6250862045 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/client/RedissonClient.java @@ -0,0 +1,148 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis.client; + +import static org.apache.eventmesh.connector.redis.config.ConfigurationWrapper.getPropertiesByPrefix; +import static org.apache.eventmesh.connector.redis.config.ConfigurationWrapper.getProperty; + +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.connector.redis.cloudevent.CloudEventCodec; +import org.apache.eventmesh.connector.redis.config.ConfigOptions; +import org.apache.eventmesh.connector.redis.config.RedisProperties; + +import java.util.Arrays; + +import org.redisson.Redisson; +import org.redisson.config.Config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +/** + * Within EventMesh's JVM, there is no multi-connector server, and redisson itself is pooled management, + * so a single instance is fine, and it can save resources and improve performance. + */ +public final class RedissonClient { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + public static final Redisson INSTANCE; + + static { + OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + + INSTANCE = create(); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + try { + INSTANCE.shutdown(); + } catch (Exception ignore) { + // + } + })); + } + + public static Redisson create() { + RedisProperties properties = new RedisProperties(); + String serverTypeName = getProperty(ConfigOptions.SERVER_TYPE); + if (serverTypeName != null) { + try { + properties.setServerType(RedisProperties.ServerType.valueOf(serverTypeName)); + } catch (Exception e) { + final String message = "Invalid Redis server type: " + properties.getServerType() + + ", supported values are: " + + Arrays.toString(RedisProperties.ServerType.values()); + throw new ConnectorRuntimeException(message, e); + } + } else { + properties.setServerType(RedisProperties.ServerType.SINGLE); + } + + String serverAddress = getProperty(ConfigOptions.SERVER_ADDRESS); + if (serverAddress != null) { + properties.setServerAddress(serverAddress); + } else { + throw new ConnectorRuntimeException("Lack Redis server address"); + } + + String serverMasterName = getProperty(ConfigOptions.SERVER_MASTER_NAME); + if (serverMasterName != null) { + properties.setServerMasterName(serverMasterName); + } + + String serverPassword = getProperty(ConfigOptions.SERVER_PASSWORD); + if (serverPassword != null) { + properties.setServerPassword(serverPassword); + } + + properties.setRedissonProperties(getPropertiesByPrefix(ConfigOptions.REDISSON_PROPERTIES_PREFIX)); + + return create(properties); + } + + private static Redisson create(RedisProperties properties) { + RedisProperties.ServerType serverType; + try { + serverType = properties.getServerType(); + } catch (IllegalArgumentException ie) { + final String message = "Invalid Redis server type: " + properties.getServerType() + + ", supported values are: " + + Arrays.toString(RedisProperties.ServerType.values()); + throw new ConnectorRuntimeException(message, ie); + } + + String serverAddress = properties.getServerAddress(); + String serverPassword = properties.getServerPassword(); + String masterName = properties.getServerMasterName(); + + Config config = OBJECT_MAPPER.convertValue(properties.getRedissonProperties(), Config.class); + + if (config == null) { + config = new Config(); + } + + config.setCodec(CloudEventCodec.INSTANCE); + + switch (serverType) { + case SINGLE: + config.useSingleServer() + .setAddress(serverAddress) + .setPassword(serverPassword); + break; + case CLUSTER: + config.useClusterServers() + .addNodeAddress(serverAddress.split(Constants.COMMA)) + .setPassword(serverPassword); + break; + case SENTINEL: + config.useSentinelServers() + .setMasterName(masterName) + .addSentinelAddress(serverAddress) + .setPassword(serverPassword); + break; + default: + final String message = "Invalid Redis server type: " + properties.getServerType() + + ", supported values are: " + + Arrays.toString(RedisProperties.ServerType.values()); + throw new ConnectorRuntimeException(message); + } + + return (Redisson) Redisson.create(config); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/cloudevent/CloudEventCodec.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/cloudevent/CloudEventCodec.java new file mode 100644 index 0000000000..7d15855060 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/cloudevent/CloudEventCodec.java @@ -0,0 +1,60 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis.cloudevent; + +import org.redisson.client.codec.BaseCodec; +import org.redisson.client.protocol.Decoder; +import org.redisson.client.protocol.Encoder; + +import io.cloudevents.CloudEvent; +import io.cloudevents.jackson.JsonFormat; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; + + +public class CloudEventCodec extends BaseCodec { + + public static final CloudEventCodec INSTANCE = new CloudEventCodec(); + + private static final JsonFormat jsonFormat = new JsonFormat(false, true); + + private static final Encoder encoder = in -> { + ByteBuf out = ByteBufAllocator.DEFAULT.buffer(); + if (in instanceof CloudEvent) { + out.writeBytes(jsonFormat.serialize((CloudEvent) in)); + return out; + } + throw new IllegalStateException("Illegal object type: " + in.getClass().getSimpleName()); + }; + + private static final Decoder decoder = (buf, state) -> { + final byte[] bytes = new byte[buf.readableBytes()]; + buf.getBytes(buf.readerIndex(), bytes); + return jsonFormat.deserialize(bytes); + }; + + @Override + public Decoder getValueDecoder() { + return decoder; + } + + @Override + public Encoder getValueEncoder() { + return encoder; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/config/ConfigOptions.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/config/ConfigOptions.java new file mode 100644 index 0000000000..f882a866fd --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/config/ConfigOptions.java @@ -0,0 +1,51 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis.config; + +/** + * Redis connector related configuration options. + */ +public interface ConfigOptions { + + /** + * The redis server configuration to be used, default is SINGLE. + */ + String SERVER_TYPE = "eventMesh.server.redis.serverType"; + + /** + * The master server name used by Redis Sentinel servers and master change monitoring task, default is master. + */ + String SERVER_MASTER_NAME = "eventMesh.server.redis.serverMasterName"; + + /** + * The address of the redis server following format -- host1:port1,host2:port2,…… + */ + String SERVER_ADDRESS = "eventMesh.server.redis.serverAddress"; + + /** + * The password for redis authentication. + */ + String SERVER_PASSWORD = "eventMesh.server.redis.serverPassword"; + + /** + * The redisson options, redisson properties, please refer to the redisson manual. + *

+ * For example, the redisson timeout property is configured as eventMesh.server.redis.redisson.timeout + */ + String REDISSON_PROPERTIES_PREFIX = "eventMesh.server.redis.redisson"; +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/config/ConfigurationWrapper.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/config/ConfigurationWrapper.java new file mode 100644 index 0000000000..0bf743a784 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/config/ConfigurationWrapper.java @@ -0,0 +1,74 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis.config; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.utils.PropertiesUtils; + +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ConfigurationWrapper { + + private static final String CONF_FILE = "redis-client.properties"; + + private static final Properties properties = new Properties(); + + static { + loadProperties(); + } + + public static String getProperty(String key) { + return StringUtils.isEmpty(key) + ? null : properties.getProperty(key, null); + } + + public static Properties getPropertiesByPrefix(String prefix) { + if (StringUtils.isBlank(prefix)) { + return null; + } + + return PropertiesUtils.getPropertiesByPrefix(properties, prefix); + } + + private static void loadProperties() { + try (InputStream resourceAsStream = ConfigurationWrapper.class.getResourceAsStream( + "/" + CONF_FILE)) { + if (resourceAsStream != null) { + properties.load(resourceAsStream); + } + } catch (IOException e) { + log.error(String.format("Load %s file from classpath error", CONF_FILE), e); + throw new RuntimeException(String.format("Load %s file from classpath error", CONF_FILE)); + } + try { + String configPath = Constants.EVENTMESH_CONF_HOME + File.separator + CONF_FILE; + PropertiesUtils.loadPropertiesWhenFileExist(properties, configPath); + } catch (IOException e) { + log.error(String.format("Cannot load %s file from conf", CONF_FILE), e); + throw new IllegalArgumentException(String.format("Cannot load %s file from conf", CONF_FILE)); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/config/RedisProperties.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/config/RedisProperties.java new file mode 100644 index 0000000000..7e5d7b20ed --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/config/RedisProperties.java @@ -0,0 +1,94 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis.config; + +import java.util.Properties; + +public class RedisProperties { + + /** + * The redis server configuration to be used. + */ + private ServerType serverType = ServerType.SINGLE; + + /** + * The master server name used by Redis Sentinel servers and master change monitoring task. + */ + private String serverMasterName = "master"; + + /** + * The address of the redis server following format -- host1:port1,host2:port2,…… + */ + private String serverAddress; + + /** + * The password for redis authentication. + */ + private String serverPassword; + + /** + * The redisson options, redisson properties, please refer to the redisson manual. + */ + private Properties redissonProperties; + + public ServerType getServerType() { + return serverType; + } + + public void setServerType(ServerType serverType) { + this.serverType = serverType; + } + + public String getServerAddress() { + return serverAddress; + } + + public void setServerAddress(String serverAddress) { + this.serverAddress = serverAddress; + } + + public String getServerPassword() { + return serverPassword; + } + + public void setServerPassword(String serverPassword) { + this.serverPassword = serverPassword; + } + + public String getServerMasterName() { + return serverMasterName; + } + + public void setServerMasterName(String serverMasterName) { + this.serverMasterName = serverMasterName; + } + + public Properties getRedissonProperties() { + return redissonProperties; + } + + public void setRedissonProperties(Properties redissonProperties) { + this.redissonProperties = redissonProperties; + } + + public enum ServerType { + SINGLE, + CLUSTER, + SENTINEL + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/connector/RedisConnectorResourceService.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/connector/RedisConnectorResourceService.java new file mode 100644 index 0000000000..13653b1731 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/connector/RedisConnectorResourceService.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis.connector; + +import org.apache.eventmesh.api.connector.ConnectorResourceService; + +public class RedisConnectorResourceService implements ConnectorResourceService { + + @Override + public void init() throws Exception { + + } + + @Override + public void release() throws Exception { + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/consumer/RedisConsumer.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/consumer/RedisConsumer.java new file mode 100644 index 0000000000..511b0339b2 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/consumer/RedisConsumer.java @@ -0,0 +1,131 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis.consumer; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.api.EventMeshAsyncConsumeContext; +import org.apache.eventmesh.api.consumer.Consumer; +import org.apache.eventmesh.connector.redis.client.RedissonClient; + +import java.util.List; +import java.util.Properties; + +import org.redisson.Redisson; +import org.redisson.api.listener.MessageListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; + +import com.google.common.base.Preconditions; + +public class RedisConsumer implements Consumer { + + private static final Logger logger = LoggerFactory.getLogger(RedisConsumer.class); + + private Redisson redisson; + + private EventMeshMessageListener messageListener; + + private volatile boolean started = false; + + @Override + public boolean isStarted() { + return started; + } + + @Override + public boolean isClosed() { + return !isStarted(); + } + + @Override + public synchronized void start() { + if (!started) { + started = true; + } + } + + @Override + public synchronized void shutdown() { + if (started) { + redisson = null; + messageListener = null; + started = false; + } + } + + @Override + public void init(Properties keyValue) { + // Currently, 'keyValue' does not pass useful configuration information. + redisson = RedissonClient.INSTANCE; + } + + @Override + public void updateOffset(List cloudEvents, AbstractContext context) { + + } + + @Override + public void subscribe(String topic) { + Preconditions.checkNotNull(topic); + Preconditions.checkNotNull(messageListener); + + redisson.getTopic(topic).addListenerAsync(CloudEvent.class, messageListener); + } + + @Override + public void unsubscribe(String topic) { + Preconditions.checkNotNull(topic); + Preconditions.checkNotNull(messageListener); + + redisson.getTopic(topic).removeListenerAsync(messageListener); + } + + @Override + public void registerEventListener(EventListener listener) { + Preconditions.checkNotNull(listener); + + messageListener = new EventMeshMessageListener(listener); + } + + static class EventMeshMessageListener implements MessageListener { + + private final EventListener listener; + + EventMeshMessageListener(EventListener listener) { + this.listener = listener; + } + + @Override + public void onMessage(CharSequence channel, CloudEvent msg) { + + final EventMeshAsyncConsumeContext consumeContext = new EventMeshAsyncConsumeContext() { + @Override + public void commit(EventMeshAction action) { + logger.info("channel: {} consumer event: {} finish action: {}", + channel, msg.getId(), action); + } + }; + + listener.consume(msg, consumeContext); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/producer/RedisProducer.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/producer/RedisProducer.java new file mode 100644 index 0000000000..5fb7d13c8a --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/java/org/apache/eventmesh/connector/redis/producer/RedisProducer.java @@ -0,0 +1,139 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis.producer; + +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.api.exception.OnExceptionContext; +import org.apache.eventmesh.api.producer.Producer; +import org.apache.eventmesh.connector.redis.client.RedissonClient; + +import java.util.Properties; + +import org.redisson.Redisson; +import org.redisson.api.RTopic; + +import io.cloudevents.CloudEvent; + +import com.google.common.base.Preconditions; + +public class RedisProducer implements Producer { + + private Redisson redisson; + + private volatile boolean started = false; + + @Override + public boolean isStarted() { + return started; + } + + @Override + public boolean isClosed() { + return !isStarted(); + } + + @Override + public synchronized void start() { + if (!started) { + started = true; + } + } + + @Override + public synchronized void shutdown() { + if (started) { + try { + redisson = null; + } finally { + started = false; + } + } + } + + @Override + public void init(Properties properties) { + // Currently, 'properties' does not pass useful configuration information. + redisson = RedissonClient.INSTANCE; + } + + @Override + public void publish(CloudEvent cloudEvent, SendCallback sendCallback) { + Preconditions.checkNotNull(cloudEvent); + Preconditions.checkNotNull(sendCallback); + + try { + RTopic topic = redisson.getTopic(cloudEvent.getSubject()); + + topic.publishAsync(cloudEvent).whenCompleteAsync((stage, throwable) -> { + if (throwable != null) { + sendCallback.onException( + OnExceptionContext.builder() + .topic(cloudEvent.getSubject()) + .messageId(cloudEvent.getId()) + .exception(new ConnectorRuntimeException(throwable)) + .build() + ); + } else { + SendResult sendResult = new SendResult(); + sendResult.setTopic(cloudEvent.getSubject()); + sendResult.setMessageId(cloudEvent.getId()); + sendCallback.onSuccess(sendResult); + } + }); + } catch (Exception e) { + sendCallback.onException( + OnExceptionContext.builder() + .topic(cloudEvent.getSubject()) + .messageId(cloudEvent.getId()) + .exception(new ConnectorRuntimeException(e)) + .build() + ); + } + } + + @Override + public void sendOneway(CloudEvent cloudEvent) { + Preconditions.checkNotNull(cloudEvent); + + RTopic topic = redisson.getTopic(cloudEvent.getSubject()); + topic.publish(cloudEvent); + } + + @Override + public void request(CloudEvent cloudEvent, RequestReplyCallback rrCallback, long timeout) { + throw new ConnectorRuntimeException("Request is not supported"); + } + + @Override + public boolean reply(CloudEvent cloudEvent, SendCallback sendCallback) { + throw new ConnectorRuntimeException("Reply is not supported"); + } + + @Override + public void checkTopicExist(String topic) { + // Because redis has the feature of creating topics when used, there is no need to check existence. + } + + @Override + public void setExtFields() { + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService new file mode 100644 index 0000000000..24d10e39bc --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService @@ -0,0 +1,16 @@ +# 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. + +redis=org.apache.eventmesh.connector.redis.connector.RedisConnectorResourceService \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer new file mode 100644 index 0000000000..e91051e77f --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer @@ -0,0 +1,16 @@ +# 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. + +redis=org.apache.eventmesh.connector.redis.consumer.RedisConsumer \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer new file mode 100644 index 0000000000..f6e6c8b76e --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer @@ -0,0 +1,16 @@ +# 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. + +redis=org.apache.eventmesh.connector.redis.producer.RedisProducer \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/resources/redis-client.properties b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/resources/redis-client.properties new file mode 100644 index 0000000000..6222972176 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/main/resources/redis-client.properties @@ -0,0 +1,17 @@ +# +# 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. +# + diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/AbstractRedisServer.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/AbstractRedisServer.java new file mode 100644 index 0000000000..93914ca712 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/AbstractRedisServer.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis; + +import org.junit.AfterClass; +import org.junit.BeforeClass; + +import ai.grakn.redismock.RedisServer; + +public abstract class AbstractRedisServer { + + private static RedisServer redisServer; + + @BeforeClass + public static void setupRedisServer() throws Exception { + redisServer = RedisServer.newRedisServer(6379); + redisServer.start(); + } + + @AfterClass + public static void shutdownRedisServer() { + if (redisServer != null) { + redisServer.stop(); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/client/RedissonClientTest.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/client/RedissonClientTest.java new file mode 100644 index 0000000000..44e5c1ba3d --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/client/RedissonClientTest.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis.client; + +import org.apache.eventmesh.connector.redis.AbstractRedisServer; + +import org.junit.Assert; +import org.junit.Test; + +public class RedissonClientTest extends AbstractRedisServer { + + @Test + public void testInstance() { + Assert.assertNotNull(RedissonClient.INSTANCE); + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/connector/UnitTest.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/connector/UnitTest.java new file mode 100644 index 0000000000..1b9072914c --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/connector/UnitTest.java @@ -0,0 +1,110 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis.connector; + +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.api.exception.OnExceptionContext; +import org.apache.eventmesh.connector.redis.AbstractRedisServer; +import org.apache.eventmesh.connector.redis.consumer.RedisConsumer; +import org.apache.eventmesh.connector.redis.consumer.RedisConsumerTest; +import org.apache.eventmesh.connector.redis.producer.RedisProducer; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.time.OffsetDateTime; +import java.util.Properties; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; + +public class UnitTest extends AbstractRedisServer { + + private RedisProducer redisProducer; + + private RedisConsumer redisConsumer; + + @Before + public void setup() { + redisProducer = new RedisProducer(); + redisProducer.init(new Properties()); + redisProducer.start(); + + redisConsumer = new RedisConsumer(); + redisConsumer.init(new Properties()); + redisConsumer.start(); + } + + @After + public void shutdown() { + redisProducer.shutdown(); + redisConsumer.shutdown(); + } + + @Test + public void testPubSub() throws Exception { + + final int expectedCount = 3; + final CountDownLatch downLatch = new CountDownLatch(expectedCount); + + redisConsumer.registerEventListener((cloudEvent, context) -> { + downLatch.countDown(); + context.commit(EventMeshAction.CommitMessage); + } + ); + + final String topic = RedisConsumerTest.class.getSimpleName(); + + redisConsumer.subscribe(topic); + + for (int i = 0; i < expectedCount; i++) { + CloudEvent cloudEvent = CloudEventBuilder.v1() + .withId(String.valueOf(i)) + .withTime(OffsetDateTime.now()) + .withSource(URI.create("testsource")) + .withSubject(topic) + .withType(String.class.getCanonicalName()) + .withDataContentType("text/plain") + .withData("data".getBytes(StandardCharsets.UTF_8)) + .build(); + + redisProducer.publish(cloudEvent, new SendCallback() { + + @Override + public void onSuccess(SendResult sendResult) { + + } + + @Override + public void onException(OnExceptionContext context) { + + } + }); + } + + Assert.assertTrue(downLatch.await(5, TimeUnit.MINUTES)); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/consumer/RedisConsumerTest.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/consumer/RedisConsumerTest.java new file mode 100644 index 0000000000..9609672cbb --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/consumer/RedisConsumerTest.java @@ -0,0 +1,91 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis.consumer; + +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.connector.redis.AbstractRedisServer; +import org.apache.eventmesh.connector.redis.client.RedissonClient; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.time.OffsetDateTime; +import java.util.Properties; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.redisson.api.RTopic; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; + +public class RedisConsumerTest extends AbstractRedisServer { + + private RedisConsumer redisConsumer; + + @Before + public void setup() { + redisConsumer = new RedisConsumer(); + redisConsumer.init(new Properties()); + redisConsumer.start(); + } + + @After + public void shutdown() { + redisConsumer.shutdown(); + } + + @Test + public void testSubscribe() throws Exception { + + final int expectedCount = 3; + final CountDownLatch downLatch = new CountDownLatch(expectedCount); + + redisConsumer.registerEventListener((cloudEvent, context) -> { + downLatch.countDown(); + context.commit(EventMeshAction.CommitMessage); + } + ); + + final String topic = RedisConsumerTest.class.getSimpleName(); + + redisConsumer.subscribe(topic); + + RTopic redissonTopic = RedissonClient.INSTANCE.getTopic(topic); + for (int i = 0; i < expectedCount; i++) { + CloudEvent cloudEvent = CloudEventBuilder.v1() + .withId(String.valueOf(i)) + .withTime(OffsetDateTime.now()) + .withSource(URI.create("testsource")) + .withSubject("topic") + .withType(String.class.getCanonicalName()) + .withDataContentType("text/plain") + .withData("data".getBytes(StandardCharsets.UTF_8)) + .build(); + + redissonTopic.publish(cloudEvent); + } + + Assert.assertTrue(downLatch.await(5, TimeUnit.MINUTES)); + + redisConsumer.unsubscribe(topic); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/producer/RedisProducerTest.java b/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/producer/RedisProducerTest.java new file mode 100644 index 0000000000..15dd65ff09 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/java/org/apache/eventmesh/connector/redis/producer/RedisProducerTest.java @@ -0,0 +1,110 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.redis.producer; + +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.api.exception.OnExceptionContext; +import org.apache.eventmesh.connector.redis.AbstractRedisServer; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.time.OffsetDateTime; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; + +public class RedisProducerTest extends AbstractRedisServer { + + private RedisProducer redisProducer; + + @Before + public void setup() { + redisProducer = new RedisProducer(); + redisProducer.init(new Properties()); + redisProducer.start(); + } + + @After + public void shutdown() { + redisProducer.shutdown(); + } + + @Test + public void testPublish() throws Exception { + final int expectedCount = 3; + final CountDownLatch downLatch = new CountDownLatch(expectedCount); + + for (int i = 0; i < expectedCount; i++) { + CloudEvent cloudEvent = CloudEventBuilder.v1() + .withId(String.valueOf(i)) + .withTime(OffsetDateTime.now()) + .withSource(URI.create("testsource")) + .withSubject(RedisProducerTest.class.getSimpleName()) + .withType(String.class.getCanonicalName()) + .withDataContentType("text/plain") + .withData("data".getBytes(StandardCharsets.UTF_8)) + .build(); + + redisProducer.publish(cloudEvent, new SendCallback() { + + @Override + public void onSuccess(SendResult sendResult) { + downLatch.countDown(); + Assert.assertEquals(cloudEvent.getId(), sendResult.getMessageId()); + Assert.assertEquals(cloudEvent.getSubject(), sendResult.getTopic()); + } + + @Override + public void onException(OnExceptionContext context) { + downLatch.countDown(); + Assert.assertEquals(cloudEvent.getId(), context.getMessageId()); + Assert.assertEquals(cloudEvent.getSubject(), context.getTopic()); + } + }); + } + + downLatch.await(); + } + + @Test + public void testSendOneway() { + + final String topic = RedisProducerTest.class.getSimpleName(); + + CloudEvent cloudEvent = CloudEventBuilder.v1() + .withId(UUID.randomUUID().toString()) + .withTime(OffsetDateTime.now()) + .withSource(URI.create("testsource")) + .withSubject(topic) + .withType(String.class.getCanonicalName()) + .withDataContentType("text/plain") + .withData("data".getBytes()) + .build(); + + redisProducer.sendOneway(cloudEvent); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/resources/redis-client.properties b/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/resources/redis-client.properties new file mode 100644 index 0000000000..9151c027ee --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-redis/src/test/resources/redis-client.properties @@ -0,0 +1,18 @@ +# +# 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. +# + +eventMesh.server.redis.serverAddress=redis://127.0.0.1:6379 \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/build.gradle b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/build.gradle new file mode 100644 index 0000000000..939cd7b722 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/build.gradle @@ -0,0 +1,59 @@ +/* + * 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. + */ + +configurations { + implementation.exclude group: 'ch.qos.logback', module: 'logback-classic' + implementation.exclude group: 'log4j', module: 'log4j' +} + +List rocketmq = [ + "org.apache.rocketmq:rocketmq-client:$rocketmq_version", + "org.apache.rocketmq:rocketmq-broker:$rocketmq_version", + "org.apache.rocketmq:rocketmq-common:$rocketmq_version", + "org.apache.rocketmq:rocketmq-store:$rocketmq_version", + "org.apache.rocketmq:rocketmq-namesrv:$rocketmq_version", + "org.apache.rocketmq:rocketmq-tools:$rocketmq_version", + "org.apache.rocketmq:rocketmq-remoting:$rocketmq_version", + "org.apache.rocketmq:rocketmq-logging:$rocketmq_version", + "org.apache.rocketmq:rocketmq-test:$rocketmq_version", + "org.apache.rocketmq:rocketmq-srvutil:$rocketmq_version", + "org.apache.rocketmq:rocketmq-filter:$rocketmq_version", + "org.apache.rocketmq:rocketmq-acl:$rocketmq_version", + "org.apache.rocketmq:rocketmq-srvutil:$rocketmq_version", + +] + +dependencies { + implementation project(":eventmesh-common") + implementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + implementation rocketmq + + testImplementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + testImplementation project(":eventmesh-common") + + testImplementation "org.mockito:mockito-core" + testImplementation "org.powermock:powermock-module-junit4" + testImplementation "org.powermock:powermock-api-mockito2" + + testImplementation rocketmq + + compileOnly 'org.projectlombok:lombok:1.18.22' + annotationProcessor 'org.projectlombok:lombok:1.18.22' + + testCompileOnly 'org.projectlombok:lombok:1.18.22' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.22' +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/gradle.properties b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/gradle.properties new file mode 100644 index 0000000000..120504127f --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/gradle.properties @@ -0,0 +1,18 @@ +# 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. +# +rocketmq_version=4.9.3 +pluginType=connector +pluginName=rocketmq \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/admin/RocketMQAdmin.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/admin/RocketMQAdmin.java new file mode 100644 index 0000000000..85857638ad --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/admin/RocketMQAdmin.java @@ -0,0 +1,171 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.admin; + +import org.apache.eventmesh.api.admin.Admin; +import org.apache.eventmesh.api.admin.TopicProperties; +import org.apache.eventmesh.connector.rocketmq.config.ClientConfiguration; + +import org.apache.commons.lang3.StringUtils; +import org.apache.rocketmq.acl.common.AclClientRPCHook; +import org.apache.rocketmq.acl.common.SessionCredentials; +import org.apache.rocketmq.common.TopicConfig; +import org.apache.rocketmq.common.admin.TopicOffset; +import org.apache.rocketmq.common.admin.TopicStatsTable; +import org.apache.rocketmq.common.message.MessageQueue; +import org.apache.rocketmq.remoting.RPCHook; +import org.apache.rocketmq.tools.admin.DefaultMQAdminExt; +import org.apache.rocketmq.tools.command.CommandUtil; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; + +import io.cloudevents.CloudEvent; + +public class RocketMQAdmin implements Admin { + private final AtomicBoolean isStarted; + + protected DefaultMQAdminExt adminExt; + + protected String nameServerAddr; + + protected String clusterName; + + private int numOfQueue = 4; + private int queuePermission = 6; + + public RocketMQAdmin(Properties properties) { + isStarted = new AtomicBoolean(false); + + final ClientConfiguration clientConfiguration = new ClientConfiguration(); + clientConfiguration.init(); + + nameServerAddr = clientConfiguration.namesrvAddr; + clusterName = clientConfiguration.clusterName; + String accessKey = clientConfiguration.accessKey; + String secretKey = clientConfiguration.secretKey; + + RPCHook rpcHook = new AclClientRPCHook(new SessionCredentials(accessKey, secretKey)); + adminExt = new DefaultMQAdminExt(rpcHook); + String groupId = UUID.randomUUID().toString(); + adminExt.setAdminExtGroup("admin_ext_group-" + groupId); + adminExt.setNamesrvAddr(nameServerAddr); + } + + @Override + public boolean isStarted() { + return isStarted.get(); + } + + @Override + public boolean isClosed() { + return !isStarted.get(); + } + + @Override + public void start() { + isStarted.compareAndSet(false, true); + } + + @Override + public void shutdown() { + isStarted.compareAndSet(true, false); + } + + @Override + public void init(Properties keyValue) throws Exception { + } + + @Override + public List getTopic() throws Exception { + try { + adminExt.start(); + List result = new ArrayList<>(); + + Set topicList = adminExt.fetchAllTopicList().getTopicList(); + for (String topic : topicList) { + long messageCount = 0; + TopicStatsTable topicStats = adminExt.examineTopicStats(topic); + HashMap offsetTable = topicStats.getOffsetTable(); + for (TopicOffset topicOffset : offsetTable.values()) { + messageCount += topicOffset.getMaxOffset() - topicOffset.getMinOffset(); + } + result.add(new TopicProperties( + topic, messageCount + )); + } + + result.sort(Comparator.comparing(t -> t.name)); + return result; + } finally { + adminExt.shutdown(); + } + } + + @Override + public void createTopic(String topicName) throws Exception { + if (StringUtils.isBlank(topicName)) { + throw new Exception("Topic name can not be blank"); + } + try { + adminExt.start(); + Set brokerAddress = CommandUtil.fetchMasterAddrByClusterName(adminExt, clusterName); + for (String masterAddress : brokerAddress) { + TopicConfig topicConfig = new TopicConfig(); + topicConfig.setTopicName(topicName); + topicConfig.setReadQueueNums(numOfQueue); + topicConfig.setWriteQueueNums(numOfQueue); + topicConfig.setPerm(queuePermission); + adminExt.createAndUpdateTopicConfig(masterAddress, topicConfig); + } + } finally { + adminExt.shutdown(); + } + } + + @Override + public void deleteTopic(String topicName) throws Exception { + if (StringUtils.isBlank(topicName)) { + throw new Exception("Topic name can not be blank."); + } + try { + adminExt.start(); + Set brokerAddress = CommandUtil.fetchMasterAddrByClusterName(adminExt, clusterName); + adminExt.deleteTopicInBroker(brokerAddress, topicName); + } finally { + adminExt.shutdown(); + } + } + + @Override + public List getEvent(String topicName, int offset, int length) throws Exception { + return null; + } + + @Override + public void publish(CloudEvent cloudEvent) throws Exception { + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/admin/RocketMQAdminAdaptor.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/admin/RocketMQAdminAdaptor.java new file mode 100644 index 0000000000..30134e8c51 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/admin/RocketMQAdminAdaptor.java @@ -0,0 +1,86 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.admin; + +import org.apache.eventmesh.api.admin.Admin; +import org.apache.eventmesh.api.admin.TopicProperties; + +import java.util.List; +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +public class RocketMQAdminAdaptor implements Admin { + + private RocketMQAdmin admin; + + public RocketMQAdminAdaptor() { + } + + @Override + public boolean isStarted() { + return admin.isStarted(); + } + + @Override + public boolean isClosed() { + return admin.isClosed(); + } + + @Override + public void start() { + admin.start(); + } + + @Override + public void shutdown() { + admin.shutdown(); + } + + @Override + public void init(Properties keyValue) throws Exception { + admin = new RocketMQAdmin(keyValue); + } + + @Override + public List getTopic() throws Exception { + return admin.getTopic(); + } + + @Override + public void createTopic(String topicName) throws Exception { + admin.createTopic(topicName); + } + + @Override + public void deleteTopic(String topicName) throws Exception { + admin.deleteTopic(topicName); + } + + @Override + public List getEvent(String topicName, int offset, int length) throws Exception { + return admin.getEvent(topicName, offset, length); + } + + @Override + public void publish(CloudEvent cloudEvent) throws Exception { + admin.publish(cloudEvent); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/cloudevent/RocketMQMessageFactory.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/cloudevent/RocketMQMessageFactory.java new file mode 100644 index 0000000000..547b308ab4 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/cloudevent/RocketMQMessageFactory.java @@ -0,0 +1,78 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.cloudevent; + +import org.apache.eventmesh.connector.rocketmq.cloudevent.impl.RocketMQBinaryMessageReader; +import org.apache.eventmesh.connector.rocketmq.cloudevent.impl.RocketMQHeaders; +import org.apache.eventmesh.connector.rocketmq.cloudevent.impl.RocketMQMessageWriter; + +import org.apache.rocketmq.common.message.Message; + +import java.util.Map; + +import javax.annotation.ParametersAreNonnullByDefault; + +import io.cloudevents.core.message.MessageReader; +import io.cloudevents.core.message.MessageWriter; +import io.cloudevents.core.message.impl.MessageUtils; +import io.cloudevents.lang.Nullable; +import io.cloudevents.rw.CloudEventRWException; +import io.cloudevents.rw.CloudEventWriter; + + +@ParametersAreNonnullByDefault +public final class RocketMQMessageFactory { + + private RocketMQMessageFactory() { + // prevent instantiation + } + + public static MessageReader createReader(final Message message) throws CloudEventRWException { + return createReader(message.getProperties(), message.getBody()); + } + + + public static MessageReader createReader(final Map props, + @Nullable final byte[] body) + throws CloudEventRWException { + + return MessageUtils.parseStructuredOrBinaryMessage( + () -> null, + format -> null, + () -> props.get(RocketMQHeaders.SPEC_VERSION), + sv -> new RocketMQBinaryMessageReader(sv, props, body) + ); + } + + + public static MessageWriter, Message> createWriter(String topic) { + return new RocketMQMessageWriter<>(topic); + } + + public static MessageWriter, Message> createWriter(String topic, + String keys) { + return new RocketMQMessageWriter<>(topic, keys); + } + + public static MessageWriter, Message> createWriter(String topic, + String keys, + String tags) { + return new RocketMQMessageWriter<>(topic, keys, tags); + } + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/cloudevent/impl/RocketMQBinaryMessageReader.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/cloudevent/impl/RocketMQBinaryMessageReader.java new file mode 100644 index 0000000000..e1d789c438 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/cloudevent/impl/RocketMQBinaryMessageReader.java @@ -0,0 +1,66 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.cloudevent.impl; + +import java.util.Map; +import java.util.Objects; +import java.util.function.BiConsumer; + +import io.cloudevents.SpecVersion; +import io.cloudevents.core.data.BytesCloudEventData; +import io.cloudevents.core.message.impl.BaseGenericBinaryMessageReaderImpl; + +public class RocketMQBinaryMessageReader + extends BaseGenericBinaryMessageReaderImpl { + + private final Map headers; + + public RocketMQBinaryMessageReader(SpecVersion version, Map headers, + byte[] payload) { + super(version, + payload != null && payload.length > 0 ? BytesCloudEventData.wrap(payload) : null); + + Objects.requireNonNull(headers); + this.headers = headers; + } + + @Override + protected boolean isContentTypeHeader(String key) { + return key.equals(RocketMQHeaders.CONTENT_TYPE); + } + + @Override + protected boolean isCloudEventsHeader(String key) { + return true; + } + + @Override + protected String toCloudEventsKey(String key) { + return key.toLowerCase(); + } + + @Override + protected void forEachHeader(BiConsumer fn) { + this.headers.forEach(fn); + } + + @Override + protected String toCloudEventsValue(String value) { + return value; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/cloudevent/impl/RocketMQHeaders.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/cloudevent/impl/RocketMQHeaders.java new file mode 100644 index 0000000000..64600ae0a7 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/cloudevent/impl/RocketMQHeaders.java @@ -0,0 +1,39 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.cloudevent.impl; + +import java.util.Map; + +import io.cloudevents.core.message.impl.MessageUtils; +import io.cloudevents.core.v1.CloudEventV1; + +public class RocketMQHeaders { + + public static final String CE_PREFIX = "CE_"; + + protected static final Map ATTRIBUTES_TO_HEADERS = + MessageUtils.generateAttributesToHeadersMapping(v -> v); + + public static final String CONTENT_TYPE = + ATTRIBUTES_TO_HEADERS.get(CloudEventV1.DATACONTENTTYPE); + + public static final String SPEC_VERSION = ATTRIBUTES_TO_HEADERS.get(CloudEventV1.SPECVERSION); + + +} + diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/cloudevent/impl/RocketMQMessageWriter.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/cloudevent/impl/RocketMQMessageWriter.java new file mode 100644 index 0000000000..4985130ba7 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/cloudevent/impl/RocketMQMessageWriter.java @@ -0,0 +1,99 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.cloudevent.impl; + +import org.apache.rocketmq.common.message.Message; + +import io.cloudevents.CloudEventData; +import io.cloudevents.SpecVersion; +import io.cloudevents.core.format.EventFormat; +import io.cloudevents.core.message.MessageWriter; +import io.cloudevents.rw.CloudEventContextWriter; +import io.cloudevents.rw.CloudEventRWException; +import io.cloudevents.rw.CloudEventWriter; + + +public final class RocketMQMessageWriter + implements MessageWriter, Message>, CloudEventWriter { + + private Message message; + + + public RocketMQMessageWriter(String topic) { + message = new Message(); + message.setTopic(topic); + } + + public RocketMQMessageWriter(String topic, String keys) { + message = new Message(); + + message.setTopic(topic); + + if (keys != null && keys.length() > 0) { + message.setKeys(keys); + } + } + + public RocketMQMessageWriter(String topic, String keys, String tags) { + message = new Message(); + + message.setTopic(topic); + + if (tags != null && tags.length() > 0) { + message.setTags(tags); + } + + if (keys != null && keys.length() > 0) { + message.setKeys(keys); + } + } + + + @Override + public CloudEventContextWriter withContextAttribute(String name, String value) + throws CloudEventRWException { + message.putUserProperty(name, value); + return this; + } + + @Override + public RocketMQMessageWriter create(final SpecVersion version) { + message.putUserProperty(RocketMQHeaders.SPEC_VERSION, version.toString()); + return this; + } + + @Override + public Message setEvent(final EventFormat format, final byte[] value) + throws CloudEventRWException { + message.putUserProperty(RocketMQHeaders.CONTENT_TYPE, format.serializedContentType()); + message.setBody(value); + return message; + } + + @Override + public Message end(final CloudEventData data) throws CloudEventRWException { + message.setBody(data.toBytes()); + return message; + } + + @Override + public Message end() { + message.setBody(null); + return message; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/common/EventMeshConstants.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/common/EventMeshConstants.java new file mode 100644 index 0000000000..1206ef9f33 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/common/EventMeshConstants.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.common; + +public class EventMeshConstants { + + public static final String EVENTMESH_CONF_FILE = "rocketmq-client.properties"; + + public static final int DEFAULT_TIMEOUT_IN_MILLISECONDS = 3000; + + public static final String STORE_TIMESTAMP = "storetime"; +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/config/ClientConfig.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/config/ClientConfig.java new file mode 100644 index 0000000000..f03a38a4a9 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/config/ClientConfig.java @@ -0,0 +1,204 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.config; + + +import org.apache.eventmesh.connector.rocketmq.domain.NonStandardKeys; + +public class ClientConfig implements NonStandardKeys { + private String driverImpl; + private String accessPoints; + private String namespace; + private String producerId; + private String consumerId; + private int operationTimeout = 5000; + private String region; + private String routingSource; + private String routingDestination; + private String routingExpression; + private String rmqConsumerGroup; + private String rmqProducerGroup = "__OMS_PRODUCER_DEFAULT_GROUP"; + private int rmqMaxRedeliveryTimes = 16; + private int rmqMessageConsumeTimeout = 15; //In minutes + private int rmqMaxConsumeThreadNums = 64; + private int rmqMinConsumeThreadNums = 20; + private String rmqMessageDestination; + private int rmqPullMessageBatchNums = 32; + private int rmqPullMessageCacheCapacity = 1000; + private String messageModel; + + public String getDriverImpl() { + return driverImpl; + } + + public void setDriverImpl(final String driverImpl) { + this.driverImpl = driverImpl; + } + + public String getAccessPoints() { + return accessPoints; + } + + public void setAccessPoints(final String accessPoints) { + this.accessPoints = accessPoints; + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(final String namespace) { + this.namespace = namespace; + } + + public String getProducerId() { + return producerId; + } + + public void setProducerId(final String producerId) { + this.producerId = producerId; + } + + public String getConsumerId() { + return consumerId; + } + + public void setConsumerId(final String consumerId) { + this.consumerId = consumerId; + } + + public int getOperationTimeout() { + return operationTimeout; + } + + public void setOperationTimeout(final int operationTimeout) { + this.operationTimeout = operationTimeout; + } + + public String getRoutingSource() { + return routingSource; + } + + public void setRoutingSource(final String routingSource) { + this.routingSource = routingSource; + } + + public String getRmqConsumerGroup() { + return rmqConsumerGroup; + } + + public void setRmqConsumerGroup(final String rmqConsumerGroup) { + this.rmqConsumerGroup = rmqConsumerGroup; + } + + public String getRmqProducerGroup() { + return rmqProducerGroup; + } + + public void setRmqProducerGroup(final String rmqProducerGroup) { + this.rmqProducerGroup = rmqProducerGroup; + } + + public int getRmqMaxRedeliveryTimes() { + return rmqMaxRedeliveryTimes; + } + + public void setRmqMaxRedeliveryTimes(final int rmqMaxRedeliveryTimes) { + this.rmqMaxRedeliveryTimes = rmqMaxRedeliveryTimes; + } + + public int getRmqMessageConsumeTimeout() { + return rmqMessageConsumeTimeout; + } + + public void setRmqMessageConsumeTimeout(final int rmqMessageConsumeTimeout) { + this.rmqMessageConsumeTimeout = rmqMessageConsumeTimeout; + } + + public int getRmqMaxConsumeThreadNums() { + return rmqMaxConsumeThreadNums; + } + + public void setRmqMaxConsumeThreadNums(final int rmqMaxConsumeThreadNums) { + this.rmqMaxConsumeThreadNums = rmqMaxConsumeThreadNums; + } + + public int getRmqMinConsumeThreadNums() { + return rmqMinConsumeThreadNums; + } + + public void setRmqMinConsumeThreadNums(final int rmqMinConsumeThreadNums) { + this.rmqMinConsumeThreadNums = rmqMinConsumeThreadNums; + } + + public String getRmqMessageDestination() { + return rmqMessageDestination; + } + + public void setRmqMessageDestination(final String rmqMessageDestination) { + this.rmqMessageDestination = rmqMessageDestination; + } + + public int getRmqPullMessageBatchNums() { + return rmqPullMessageBatchNums; + } + + public void setRmqPullMessageBatchNums(final int rmqPullMessageBatchNums) { + this.rmqPullMessageBatchNums = rmqPullMessageBatchNums; + } + + public int getRmqPullMessageCacheCapacity() { + return rmqPullMessageCacheCapacity; + } + + public void setRmqPullMessageCacheCapacity(final int rmqPullMessageCacheCapacity) { + this.rmqPullMessageCacheCapacity = rmqPullMessageCacheCapacity; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getRoutingDestination() { + return routingDestination; + } + + public void setRoutingDestination(String routingDestination) { + this.routingDestination = routingDestination; + } + + public String getRoutingExpression() { + return routingExpression; + } + + public void setRoutingExpression(String routingExpression) { + this.routingExpression = routingExpression; + } + + public String getMessageModel() { + return messageModel; + } + + public void setMessageModel(String messageModel) { + this.messageModel = messageModel; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/config/ClientConfiguration.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/config/ClientConfiguration.java new file mode 100644 index 0000000000..8fb2d3f9c0 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/config/ClientConfiguration.java @@ -0,0 +1,201 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.config; + +import org.apache.commons.lang3.StringUtils; + +import com.google.common.base.Preconditions; + +public class ClientConfiguration { + + public String namesrvAddr = ""; + public String clientUserName = "username"; + public String clientPass = "password"; + public Integer consumeThreadMin = 2; + public Integer consumeThreadMax = 2; + public Integer consumeQueueSize = 10000; + public Integer pullBatchSize = 32; + public Integer ackWindow = 1000; + public Integer pubWindow = 100; + public long consumeTimeout = 0L; + public Integer pollNameServerInterval = 10 * 1000; + public Integer heartbeatBrokerInterval = 30 * 1000; + public Integer rebalanceInterval = 20 * 1000; + public String clusterName = ""; + public String accessKey = ""; + public String secretKey = ""; + + public void init() { + + String clientUserNameStr = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_USERNAME); + if (StringUtils.isNotBlank(clientUserNameStr)) { + clientUserName = StringUtils.trim(clientUserNameStr); + } + + String clientPassStr = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_PASSWORD); + if (StringUtils.isNotBlank(clientPassStr)) { + clientPass = StringUtils.trim(clientPassStr); + } + + String namesrvAddrStr = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_NAMESRV_ADDR); + Preconditions.checkState(StringUtils.isNotEmpty(namesrvAddrStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_ROCKETMQ_NAMESRV_ADDR)); + namesrvAddr = StringUtils.trim(namesrvAddrStr); + + String consumeThreadPoolMinStr = + ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CONSUME_THREADPOOL_MIN); + if (StringUtils.isNotEmpty(consumeThreadPoolMinStr)) { + Preconditions.checkState(StringUtils.isNumeric(consumeThreadPoolMinStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CONSUME_THREADPOOL_MIN)); + consumeThreadMin = Integer.valueOf(consumeThreadPoolMinStr); + } + + String consumeThreadPoolMaxStr = + ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CONSUME_THREADPOOL_MAX); + if (StringUtils.isNotEmpty(consumeThreadPoolMaxStr)) { + Preconditions.checkState(StringUtils.isNumeric(consumeThreadPoolMaxStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CONSUME_THREADPOOL_MAX)); + consumeThreadMax = Integer.valueOf(consumeThreadPoolMaxStr); + } + + String consumerThreadPoolQueueSizeStr = + ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CONSUME_THREADPOOL_QUEUESIZE); + if (StringUtils.isNotEmpty(consumerThreadPoolQueueSizeStr)) { + Preconditions.checkState(StringUtils.isNumeric(consumerThreadPoolQueueSizeStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CONSUME_THREADPOOL_QUEUESIZE)); + consumeQueueSize = Integer.valueOf(consumerThreadPoolQueueSizeStr); + } + + String clientAckWindowStr = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_ACK_WINDOW); + if (StringUtils.isNotEmpty(clientAckWindowStr)) { + Preconditions.checkState(StringUtils.isNumeric(clientAckWindowStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_ACK_WINDOW)); + ackWindow = Integer.valueOf(clientAckWindowStr); + } + + String clientPubWindowStr = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_PUB_WINDOW); + if (StringUtils.isNotEmpty(clientPubWindowStr)) { + Preconditions.checkState(StringUtils.isNumeric(clientPubWindowStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_PUB_WINDOW)); + pubWindow = Integer.valueOf(clientPubWindowStr); + } + + String consumeTimeoutStr = + ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_CONSUME_TIMEOUT); + if (StringUtils.isNotBlank(consumeTimeoutStr)) { + Preconditions.checkState(StringUtils.isNumeric(consumeTimeoutStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_CONSUME_TIMEOUT)); + consumeTimeout = Long.parseLong(consumeTimeoutStr); + } + + String clientPullBatchSizeStr = + ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_PULL_BATCHSIZE); + if (StringUtils.isNotEmpty(clientPullBatchSizeStr)) { + Preconditions.checkState(StringUtils.isNumeric(clientPullBatchSizeStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_PULL_BATCHSIZE)); + pullBatchSize = Integer.valueOf(clientPullBatchSizeStr); + } + + String clientPollNamesrvIntervalStr = + ConfigurationWrapper.getProp( + ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_POLL_NAMESRV_INTERVAL); + if (StringUtils.isNotEmpty(clientPollNamesrvIntervalStr)) { + Preconditions.checkState(StringUtils.isNumeric(clientPollNamesrvIntervalStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_POLL_NAMESRV_INTERVAL)); + pollNameServerInterval = Integer.valueOf(clientPollNamesrvIntervalStr); + } + + String clientHeartbeatBrokerIntervalStr = + ConfigurationWrapper.getProp( + ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_HEARTBEAT_BROKER_INTERVAL); + if (StringUtils.isNotEmpty(clientHeartbeatBrokerIntervalStr)) { + Preconditions.checkState(StringUtils.isNumeric(clientHeartbeatBrokerIntervalStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_HEARTBEAT_BROKER_INTERVAL)); + heartbeatBrokerInterval = Integer.valueOf(clientHeartbeatBrokerIntervalStr); + } + + String clientRebalanceIntervalIntervalStr = + ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_REBALANCE_INTERVAL); + if (StringUtils.isNotEmpty(clientRebalanceIntervalIntervalStr)) { + Preconditions.checkState(StringUtils.isNumeric(clientRebalanceIntervalIntervalStr), + String.format("%s error", ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLIENT_REBALANCE_INTERVAL)); + rebalanceInterval = Integer.valueOf(clientRebalanceIntervalIntervalStr); + } + + String cluster = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_CLUSTER); + if (StringUtils.isNotBlank(cluster)) { + clusterName = cluster; + } + + String ak = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_ACCESS_KEY); + if (StringUtils.isNotBlank(ak)) { + accessKey = ak; + } + + String sk = ConfigurationWrapper.getProp(ConfKeys.KEYS_EVENTMESH_ROCKETMQ_SECRET_KEY); + if (StringUtils.isNotBlank(sk)) { + secretKey = sk; + } + } + + static class ConfKeys { + + public static final String KEYS_EVENTMESH_ROCKETMQ_NAMESRV_ADDR = "eventMesh.server.rocketmq.namesrvAddr"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_USERNAME = "eventMesh.server.rocketmq.username"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_PASSWORD = "eventMesh.server.rocketmq.password"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_CONSUME_THREADPOOL_MIN = + "eventMesh.server.rocketmq.client.consumeThreadMin"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_CONSUME_THREADPOOL_MAX = + "eventMesh.server.rocketmq.client.consumeThreadMax"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_CONSUME_THREADPOOL_QUEUESIZE = + "eventMesh.server.rocketmq.client.consumeThreadPoolQueueSize"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_CLIENT_ACK_WINDOW = "eventMesh.server.rocketmq.client.ackwindow"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_CLIENT_PUB_WINDOW = "eventMesh.server.rocketmq.client.pubwindow"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_CLIENT_CONSUME_TIMEOUT = + "eventMesh.server.rocketmq.client.comsumeTimeoutInMin"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_CLIENT_PULL_BATCHSIZE = + "eventMesh.server.rocketmq.client.pullBatchSize"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_CLIENT_POLL_NAMESRV_INTERVAL = + "eventMesh.server.rocketmq.client.pollNameServerInterval"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_CLIENT_HEARTBEAT_BROKER_INTERVAL = + "eventMesh.server.rocketmq.client.heartbeatBrokerInterval"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_CLIENT_REBALANCE_INTERVAL = + "eventMesh.server.rocketmq.client.rebalanceInterval"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_CLUSTER = "eventMesh.server.rocketmq.cluster"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_ACCESS_KEY = + "eventMesh.server.rocketmq.accessKey"; + + public static final String KEYS_EVENTMESH_ROCKETMQ_SECRET_KEY = + "eventMesh.server.rocketmq.secretKey"; + + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/config/ConfigurationWrapper.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/config/ConfigurationWrapper.java new file mode 100644 index 0000000000..af5faceb35 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/config/ConfigurationWrapper.java @@ -0,0 +1,68 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.config; + +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.common.utils.PropertiesUtils; +import org.apache.eventmesh.connector.rocketmq.common.EventMeshConstants; + +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@UtilityClass +public class ConfigurationWrapper { + + private static final Properties properties = new Properties(); + + static { + loadProperties(); + } + + public String getProp(String key) { + return StringUtils.isEmpty(key) ? null : properties.getProperty(key, null); + } + + /** + * Load rocketmq properties file from classpath and conf home. + * The properties defined in conf home will override classpath. + */ + private void loadProperties() { + try (InputStream resourceAsStream = ConfigurationWrapper.class.getResourceAsStream( + "/" + EventMeshConstants.EVENTMESH_CONF_FILE)) { + if (resourceAsStream != null) { + properties.load(resourceAsStream); + } + } catch (IOException e) { + throw new RuntimeException(String.format("Load %s.properties file from classpath error", EventMeshConstants.EVENTMESH_CONF_FILE)); + } + try { + String configPath = Constants.EVENTMESH_CONF_HOME + File.separator + EventMeshConstants.EVENTMESH_CONF_FILE; + PropertiesUtils.loadPropertiesWhenFileExist(properties, configPath); + } catch (IOException e) { + throw new IllegalArgumentException(String.format("Cannot load %s file from conf", EventMeshConstants.EVENTMESH_CONF_FILE)); + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/connector/ConnectorResourceServiceRocketmqImpl.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/connector/ConnectorResourceServiceRocketmqImpl.java new file mode 100644 index 0000000000..f26747e9db --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/connector/ConnectorResourceServiceRocketmqImpl.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.connector; + +import org.apache.eventmesh.api.connector.ConnectorResourceService; + +public class ConnectorResourceServiceRocketmqImpl implements ConnectorResourceService { + @Override + public void init() throws Exception { + + } + + @Override + public void release() throws Exception { + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/consumer/PushConsumerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/consumer/PushConsumerImpl.java new file mode 100644 index 0000000000..8283628bb7 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/consumer/PushConsumerImpl.java @@ -0,0 +1,310 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.consumer; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.api.EventMeshAsyncConsumeContext; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.connector.rocketmq.cloudevent.RocketMQMessageFactory; +import org.apache.eventmesh.connector.rocketmq.common.EventMeshConstants; +import org.apache.eventmesh.connector.rocketmq.config.ClientConfig; +import org.apache.eventmesh.connector.rocketmq.domain.NonStandardKeys; +import org.apache.eventmesh.connector.rocketmq.patch.EventMeshConsumeConcurrentlyContext; +import org.apache.eventmesh.connector.rocketmq.patch.EventMeshConsumeConcurrentlyStatus; +import org.apache.eventmesh.connector.rocketmq.patch.EventMeshMessageListenerConcurrently; +import org.apache.eventmesh.connector.rocketmq.utils.BeanUtils; +import org.apache.eventmesh.connector.rocketmq.utils.CloudEventUtils; +import org.apache.eventmesh.connector.rocketmq.utils.OMSUtil; + +import org.apache.commons.lang3.StringUtils; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.impl.consumer.ConsumeMessageConcurrentlyService; +import org.apache.rocketmq.client.impl.consumer.ConsumeMessageService; +import org.apache.rocketmq.common.message.MessageConst; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; +import org.apache.rocketmq.remoting.protocol.LanguageCode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; + +public class PushConsumerImpl { + private final DefaultMQPushConsumer rocketmqPushConsumer; + private final Properties properties; + private AtomicBoolean started = new AtomicBoolean(false); + private EventListener eventListener; + private final ClientConfig clientConfig; + + public PushConsumerImpl(final Properties properties) { + this.rocketmqPushConsumer = new DefaultMQPushConsumer(); + this.properties = properties; + this.clientConfig = BeanUtils.populate(properties, ClientConfig.class); + + String accessPoints = clientConfig.getAccessPoints(); + if (accessPoints == null || accessPoints.isEmpty()) { + throw new ConnectorRuntimeException("OMS AccessPoints is null or empty."); + } + this.rocketmqPushConsumer.setNamesrvAddr(accessPoints.replace(',', ';')); + String consumerGroup = clientConfig.getConsumerId(); + if (null == consumerGroup || consumerGroup.isEmpty()) { + throw new ConnectorRuntimeException( + "Consumer Group is necessary for RocketMQ, please set it."); + } + this.rocketmqPushConsumer.setConsumerGroup(consumerGroup); + this.rocketmqPushConsumer.setMaxReconsumeTimes(clientConfig.getRmqMaxRedeliveryTimes()); + this.rocketmqPushConsumer.setConsumeTimeout(clientConfig.getRmqMessageConsumeTimeout()); + this.rocketmqPushConsumer.setConsumeThreadMax(clientConfig.getRmqMaxConsumeThreadNums()); + this.rocketmqPushConsumer.setConsumeThreadMin(clientConfig.getRmqMinConsumeThreadNums()); + this.rocketmqPushConsumer.setMessageModel( + MessageModel.valueOf(clientConfig.getMessageModel())); + + String consumerId = OMSUtil.buildInstanceName(); + //this.rocketmqPushConsumer.setInstanceName(consumerId); + this.rocketmqPushConsumer.setInstanceName(properties.getProperty("instanceName")); + properties.put("CONSUMER_ID", consumerId); + this.rocketmqPushConsumer.setLanguage(LanguageCode.OMS); + + if (clientConfig.getMessageModel().equalsIgnoreCase(MessageModel.BROADCASTING.name())) { + rocketmqPushConsumer.registerMessageListener(new BroadCastingMessageListener()); + } else { + rocketmqPushConsumer.registerMessageListener(new ClusteringMessageListener()); + } + } + + public Properties attributes() { + return properties; + } + + + public void start() { + if (this.started.compareAndSet(false, true)) { + try { + this.rocketmqPushConsumer.start(); + } catch (Exception e) { + throw new ConnectorRuntimeException(e.getMessage()); + } + } + } + + + public synchronized void shutdown() { + if (this.started.compareAndSet(true, false)) { + this.rocketmqPushConsumer.shutdown(); + } + } + + + public boolean isStarted() { + return this.started.get(); + } + + + public boolean isClosed() { + return !this.isStarted(); + } + + public DefaultMQPushConsumer getRocketmqPushConsumer() { + return rocketmqPushConsumer; + } + + public void subscribe(String topic, String subExpression) { + try { + this.rocketmqPushConsumer.subscribe(topic, subExpression); + } catch (MQClientException e) { + throw new ConnectorRuntimeException(String.format("RocketMQ push consumer can't attach to %s.", topic)); + } + } + + public void unsubscribe(String topic) { + try { + this.rocketmqPushConsumer.unsubscribe(topic); + } catch (Exception e) { + throw new ConnectorRuntimeException(String.format("RocketMQ push consumer fails to unsubscribe topic: %s", topic)); + } + } + + public void updateOffset(List cloudEvents, AbstractContext context) { + ConsumeMessageService consumeMessageService = rocketmqPushConsumer + .getDefaultMQPushConsumerImpl().getConsumeMessageService(); + List msgExtList = new ArrayList<>(cloudEvents.size()); + for (CloudEvent msg : cloudEvents) { + if (msg != null) { + msgExtList.add(CloudEventUtils.msgConvertExt( + RocketMQMessageFactory.createWriter(msg.getSubject()).writeBinary(msg))); + } + } + ((ConsumeMessageConcurrentlyService) consumeMessageService) + .updateOffset(msgExtList, (EventMeshConsumeConcurrentlyContext) context); + } + + + private class BroadCastingMessageListener extends EventMeshMessageListenerConcurrently { + + @Override + public EventMeshConsumeConcurrentlyStatus handleMessage(MessageExt msg, + EventMeshConsumeConcurrentlyContext context) { + if (msg == null) { + return EventMeshConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + + msg.putUserProperty(Constants.PROPERTY_MESSAGE_BORN_TIMESTAMP, + String.valueOf(msg.getBornTimestamp())); + msg.putUserProperty(Constants.PROPERTY_MESSAGE_STORE_TIMESTAMP, + String.valueOf(msg.getStoreTimestamp())); + + //for rr request/reply + CloudEvent cloudEvent = + RocketMQMessageFactory.createReader(CloudEventUtils.msgConvert(msg)).toEvent(); + + CloudEventBuilder cloudEventBuilder = null; + for (String sysPropKey : MessageConst.STRING_HASH_SET) { + if (StringUtils.isNotEmpty(msg.getProperty(sysPropKey))) { + String prop = msg.getProperty(sysPropKey); + sysPropKey = sysPropKey.toLowerCase().replaceAll("_", Constants.MESSAGE_PROP_SEPARATOR); + cloudEventBuilder = CloudEventBuilder.from(cloudEvent).withExtension(sysPropKey, prop); + } + } + if (cloudEventBuilder != null) { + cloudEvent = cloudEventBuilder.build(); + } + + if (eventListener == null) { + throw new ConnectorRuntimeException(String.format("The topic/queue %s isn't attached to this consumer", + msg.getTopic())); + } + + final Properties contextProperties = new Properties(); + contextProperties.put(NonStandardKeys.MESSAGE_CONSUME_STATUS, + EventMeshConsumeConcurrentlyStatus.RECONSUME_LATER.name()); + EventMeshAsyncConsumeContext eventMeshAsyncConsumeContext = new EventMeshAsyncConsumeContext() { + @Override + public void commit(EventMeshAction action) { + switch (action) { + case CommitMessage: + contextProperties.put(NonStandardKeys.MESSAGE_CONSUME_STATUS, + EventMeshConsumeConcurrentlyStatus.CONSUME_SUCCESS.name()); + break; + case ReconsumeLater: + contextProperties.put(NonStandardKeys.MESSAGE_CONSUME_STATUS, + EventMeshConsumeConcurrentlyStatus.RECONSUME_LATER.name()); + break; + case ManualAck: + contextProperties.put(NonStandardKeys.MESSAGE_CONSUME_STATUS, + EventMeshConsumeConcurrentlyStatus.CONSUME_FINISH.name()); + break; + default: + break; + } + } + }; + + eventMeshAsyncConsumeContext.setAbstractContext(context); + + eventListener.consume(cloudEvent, eventMeshAsyncConsumeContext); + + return EventMeshConsumeConcurrentlyStatus.valueOf( + contextProperties.getProperty(NonStandardKeys.MESSAGE_CONSUME_STATUS)); + } + + + } + + private class ClusteringMessageListener extends EventMeshMessageListenerConcurrently { + + @Override + public EventMeshConsumeConcurrentlyStatus handleMessage(MessageExt msg, + EventMeshConsumeConcurrentlyContext context) { + if (msg == null) { + return EventMeshConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + + msg.putUserProperty(Constants.PROPERTY_MESSAGE_BORN_TIMESTAMP, + String.valueOf(msg.getBornTimestamp())); + msg.putUserProperty(EventMeshConstants.STORE_TIMESTAMP, + String.valueOf(msg.getStoreTimestamp())); + + CloudEvent cloudEvent = + RocketMQMessageFactory.createReader(CloudEventUtils.msgConvert(msg)).toEvent(); + + CloudEventBuilder cloudEventBuilder = null; + + for (String sysPropKey : MessageConst.STRING_HASH_SET) { + if (StringUtils.isNotEmpty(msg.getProperty(sysPropKey))) { + String prop = msg.getProperty(sysPropKey); + sysPropKey = sysPropKey.toLowerCase().replaceAll("_", Constants.MESSAGE_PROP_SEPARATOR); + cloudEventBuilder = CloudEventBuilder.from(cloudEvent).withExtension(sysPropKey, prop); + } + } + if (cloudEventBuilder != null) { + cloudEvent = cloudEventBuilder.build(); + } + + if (eventListener == null) { + throw new ConnectorRuntimeException(String.format("The topic/queue %s isn't attached to this consumer", + msg.getTopic())); + } + + final Properties contextProperties = new Properties(); + + contextProperties.put(NonStandardKeys.MESSAGE_CONSUME_STATUS, + EventMeshConsumeConcurrentlyStatus.RECONSUME_LATER.name()); + + EventMeshAsyncConsumeContext eventMeshAsyncConsumeContext = new EventMeshAsyncConsumeContext() { + @Override + public void commit(EventMeshAction action) { + switch (action) { + case CommitMessage: + contextProperties.put(NonStandardKeys.MESSAGE_CONSUME_STATUS, + EventMeshConsumeConcurrentlyStatus.CONSUME_SUCCESS.name()); + break; + case ReconsumeLater: + contextProperties.put(NonStandardKeys.MESSAGE_CONSUME_STATUS, + EventMeshConsumeConcurrentlyStatus.RECONSUME_LATER.name()); + break; + case ManualAck: + contextProperties.put(NonStandardKeys.MESSAGE_CONSUME_STATUS, + EventMeshConsumeConcurrentlyStatus.CONSUME_FINISH.name()); + break; + default: + break; + } + } + }; + + eventMeshAsyncConsumeContext.setAbstractContext(context); + + eventListener.consume(cloudEvent, eventMeshAsyncConsumeContext); + + return EventMeshConsumeConcurrentlyStatus.valueOf( + contextProperties.getProperty(NonStandardKeys.MESSAGE_CONSUME_STATUS)); + } + } + + public void registerEventListener(EventListener listener) { + this.eventListener = listener; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/consumer/RocketMQConsumerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/consumer/RocketMQConsumerImpl.java new file mode 100644 index 0000000000..a2630652ad --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/consumer/RocketMQConsumerImpl.java @@ -0,0 +1,116 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.consumer; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.consumer.Consumer; +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.connector.rocketmq.config.ClientConfiguration; + +import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; + +import java.util.List; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class RocketMQConsumerImpl implements Consumer { + + public Logger messageLogger = LoggerFactory.getLogger("message"); + + private PushConsumerImpl pushConsumer; + + @Override + public synchronized void init(Properties keyValue) throws Exception { + final ClientConfiguration clientConfiguration = new ClientConfiguration(); + clientConfiguration.init(); + boolean isBroadcast = Boolean.parseBoolean(keyValue.getProperty(Constants.IS_BROADCAST)); + + String consumerGroup = keyValue.getProperty(Constants.CONSUMER_GROUP); + if (isBroadcast) { + consumerGroup = Constants.BROADCAST_PREFIX + consumerGroup; + } + + String namesrvAddr = clientConfiguration.namesrvAddr; + String instanceName = keyValue.getProperty(Constants.INSTANCE_NAME); + Properties properties = new Properties(); + properties.put(Constants.ACCESS_POINTS, namesrvAddr); + properties.put(Constants.REGION, Constants.NAMESPACE); + properties.put(Constants.INSTANCE_NAME, instanceName); + properties.put(Constants.CONSUMER_ID, consumerGroup); + if (isBroadcast) { + properties.put(Constants.MESSAGE_MODEL, MessageModel.BROADCASTING.name()); + } else { + properties.put(Constants.MESSAGE_MODEL, MessageModel.CLUSTERING.name()); + } + + pushConsumer = new PushConsumerImpl(properties); + } + + @Override + public void subscribe(String topic) throws Exception { + pushConsumer.subscribe(topic, "*"); + } + + @Override + public boolean isStarted() { + return pushConsumer.isStarted(); + } + + @Override + public boolean isClosed() { + return pushConsumer.isClosed(); + } + + @Override + public synchronized void start() { + pushConsumer.start(); + } + + @Override + public void updateOffset(List cloudEvents, AbstractContext context) { + pushConsumer.updateOffset(cloudEvents, context); + } + + @Override + public void unsubscribe(String topic) { + pushConsumer.unsubscribe(topic); + } + + @Override + public void registerEventListener(EventListener listener) { + pushConsumer.registerEventListener(listener); + } + + @Override + public synchronized void shutdown() { + pushConsumer.shutdown(); + } + + public Properties attributes() { + return pushConsumer.attributes(); + } + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/domain/NonStandardKeys.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/domain/NonStandardKeys.java new file mode 100644 index 0000000000..209557dc9f --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/domain/NonStandardKeys.java @@ -0,0 +1,29 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.domain; + +/** + * NonStandardKeys + */ +public interface NonStandardKeys { + String CONSUMER_GROUP = "rmq.consumer.group"; + String MAX_REDELIVERY_TIMES = "rmq.max.redelivery.times"; + String MESSAGE_CONSUME_TIMEOUT = "rmq.message.consume.timeout"; + String MESSAGE_CONSUME_STATUS = "rmq.message.consume.status"; + String MESSAGE_DESTINATION = "rmq.message.destination"; +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/exception/RMQMessageFormatException.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/exception/RMQMessageFormatException.java new file mode 100644 index 0000000000..703b7ea2bf --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/exception/RMQMessageFormatException.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.exception; + +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; + +public class RMQMessageFormatException extends ConnectorRuntimeException { + + public RMQMessageFormatException(String message) { + super(message); + } + + public RMQMessageFormatException(Throwable throwable) { + super(throwable); + } + + public RMQMessageFormatException(String message, Throwable throwable) { + super(message, throwable); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/exception/RMQTimeoutException.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/exception/RMQTimeoutException.java new file mode 100644 index 0000000000..c2a6b03410 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/exception/RMQTimeoutException.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.exception; + +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; + +public class RMQTimeoutException extends ConnectorRuntimeException { + + public RMQTimeoutException(String message) { + super(message); + } + + public RMQTimeoutException(Throwable throwable) { + super(throwable); + } + + public RMQTimeoutException(String message, Throwable throwable) { + super(message, throwable); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/patch/EventMeshConsumeConcurrentlyContext.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/patch/EventMeshConsumeConcurrentlyContext.java new file mode 100644 index 0000000000..2dcfa95038 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/patch/EventMeshConsumeConcurrentlyContext.java @@ -0,0 +1,46 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.patch; + +import org.apache.eventmesh.api.AbstractContext; + +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.impl.consumer.ProcessQueue; +import org.apache.rocketmq.common.message.MessageQueue; + +public class EventMeshConsumeConcurrentlyContext extends ConsumeConcurrentlyContext implements AbstractContext { + private final ProcessQueue processQueue; + private boolean manualAck = true; + + public EventMeshConsumeConcurrentlyContext(MessageQueue messageQueue, ProcessQueue processQueue) { + super(messageQueue); + this.processQueue = processQueue; + } + + public ProcessQueue getProcessQueue() { + return processQueue; + } + + public boolean isManualAck() { + return manualAck; + } + + public void setManualAck(boolean manualAck) { + this.manualAck = manualAck; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/patch/EventMeshConsumeConcurrentlyStatus.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/patch/EventMeshConsumeConcurrentlyStatus.java new file mode 100644 index 0000000000..468b14f568 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/patch/EventMeshConsumeConcurrentlyStatus.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.patch; + +public enum EventMeshConsumeConcurrentlyStatus { + /** + * Success consumption + */ + CONSUME_SUCCESS, + /** + * Failure consumption,later try to consume + */ + RECONSUME_LATER, + /** + * Success consumption but ack later manually + */ + CONSUME_FINISH; +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/patch/EventMeshMessageListenerConcurrently.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/patch/EventMeshMessageListenerConcurrently.java new file mode 100644 index 0000000000..0d32ba27d3 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/patch/EventMeshMessageListenerConcurrently.java @@ -0,0 +1,72 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.patch; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.common.message.MessageExt; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class EventMeshMessageListenerConcurrently implements MessageListenerConcurrently { + + private static final Logger LOG = LoggerFactory.getLogger(EventMeshMessageListenerConcurrently.class); + + @Override + public ConsumeConcurrentlyStatus consumeMessage(final List msgs, + final ConsumeConcurrentlyContext context) { + ConsumeConcurrentlyStatus status = null; + + if (CollectionUtils.isEmpty(msgs)) { + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + + MessageExt msg = msgs.get(0); + try { + EventMeshConsumeConcurrentlyContext eventMeshConsumeConcurrentlyContext = (EventMeshConsumeConcurrentlyContext) context; + EventMeshConsumeConcurrentlyStatus eventMeshConsumeStatus = handleMessage(msg, eventMeshConsumeConcurrentlyContext); + try { + switch (eventMeshConsumeStatus) { + case CONSUME_SUCCESS: + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + case RECONSUME_LATER: + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + case CONSUME_FINISH: + eventMeshConsumeConcurrentlyContext.setManualAck(true); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + default: + return status; + } + } catch (Throwable e) { + LOG.info("handleMessage fail", e); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + } catch (Throwable e) { + LOG.info("handleMessage fail", e); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + //return status; + } + + public abstract EventMeshConsumeConcurrentlyStatus handleMessage(MessageExt msg, EventMeshConsumeConcurrentlyContext context); +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/AbstractProducer.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/AbstractProducer.java new file mode 100644 index 0000000000..6335d49d0a --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/AbstractProducer.java @@ -0,0 +1,163 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.producer; + +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.connector.rocketmq.config.ClientConfig; +import org.apache.eventmesh.connector.rocketmq.exception.RMQMessageFormatException; +import org.apache.eventmesh.connector.rocketmq.exception.RMQTimeoutException; +import org.apache.eventmesh.connector.rocketmq.utils.BeanUtils; +import org.apache.eventmesh.connector.rocketmq.utils.OMSUtil; + +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl; +import org.apache.rocketmq.client.log.ClientLogger; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.common.protocol.ResponseCode; +import org.apache.rocketmq.logging.InternalLogger; +import org.apache.rocketmq.remoting.exception.RemotingConnectException; +import org.apache.rocketmq.remoting.exception.RemotingTimeoutException; +import org.apache.rocketmq.remoting.protocol.LanguageCode; + +import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; + +public abstract class AbstractProducer { + + static final InternalLogger log = ClientLogger.getLog(); + final Properties properties; + final DefaultMQProducer rocketmqProducer; + protected final AtomicBoolean started = new AtomicBoolean(false); + // private boolean started = false; + private final ClientConfig clientConfig; + + AbstractProducer(final Properties properties) { + this.properties = properties; + this.rocketmqProducer = new DefaultMQProducer(); + this.clientConfig = BeanUtils.populate(properties, ClientConfig.class); + + String accessPoints = clientConfig.getAccessPoints(); + if (accessPoints == null || accessPoints.isEmpty()) { + throw new ConnectorRuntimeException("OMS AccessPoints is null or empty."); + } + + this.rocketmqProducer.setNamesrvAddr(accessPoints.replace(',', ';')); + + this.rocketmqProducer.setProducerGroup(clientConfig.getRmqProducerGroup()); + + String producerId = OMSUtil.buildInstanceName(); + this.rocketmqProducer.setSendMsgTimeout(clientConfig.getOperationTimeout()); + this.rocketmqProducer.setInstanceName(producerId); + this.rocketmqProducer.setMaxMessageSize(1024 * 1024 * 4); + this.rocketmqProducer.setLanguage(LanguageCode.OMS); + properties.put(Constants.PRODUCER_ID, producerId); + } + + public synchronized void start() { + if (!started.get()) { + try { + this.rocketmqProducer.start(); + } catch (MQClientException e) { + throw new ConnectorRuntimeException("-1", e); + } + } + this.started.set(true); + } + + public synchronized void shutdown() { + if (this.started.get()) { + this.rocketmqProducer.shutdown(); + } + this.started.set(false); + } + + public boolean isStarted() { + return this.started.get(); + } + + public boolean isClosed() { + return !this.isStarted(); + } + + ConnectorRuntimeException checkProducerException(String topic, String msgId, Throwable e) { + if (e instanceof MQClientException) { + if (e.getCause() != null) { + if (e.getCause() instanceof RemotingTimeoutException) { + return new RMQTimeoutException( + String.format("Send message to broker timeout, %dms, Topic=%s, msgId=%s", + this.rocketmqProducer.getSendMsgTimeout(), topic, msgId), e); + } else if (e.getCause() instanceof MQBrokerException + || e.getCause() instanceof RemotingConnectException) { + if (e.getCause() instanceof MQBrokerException) { + MQBrokerException brokerException = (MQBrokerException) e.getCause(); + return new ConnectorRuntimeException( + String.format("Received a broker exception, Topic=%s, msgId=%s, %s", + topic, msgId, brokerException.getErrorMessage()), e); + } + + if (e.getCause() instanceof RemotingConnectException) { + RemotingConnectException connectException = + (RemotingConnectException) e.getCause(); + return new ConnectorRuntimeException( + String.format( + "Network connection experiences failures. Topic=%s, msgId=%s, %s", + topic, msgId, connectException.getMessage()), e); + } + } + } else { + // Exception thrown by local. + MQClientException clientException = (MQClientException) e; + if (-1 == clientException.getResponseCode()) { + return new ConnectorRuntimeException( + String.format("Topic does not exist, Topic=%s, msgId=%s", + topic, msgId), e); + } else if (ResponseCode.MESSAGE_ILLEGAL == clientException.getResponseCode()) { + return new RMQMessageFormatException( + String.format("A illegal message for RocketMQ, Topic=%s, msgId=%s", + topic, msgId), e); + } + } + } + return new ConnectorRuntimeException("Send message to RocketMQ broker failed.", e); + } + + protected void checkProducerServiceState(DefaultMQProducerImpl producer) { + switch (producer.getServiceState()) { + case CREATE_JUST: + throw new ConnectorRuntimeException( + String.format("You do not have start the producer, %s", + producer.getServiceState())); + case SHUTDOWN_ALREADY: + throw new ConnectorRuntimeException( + String.format("Your producer has been shut down, %s", + producer.getServiceState())); + case START_FAILED: + throw new ConnectorRuntimeException( + String.format("When you start your service throws an exception, %s", + producer.getServiceState())); + case RUNNING: + default: + } + } + + public DefaultMQProducer getRocketmqProducer() { + return rocketmqProducer; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/ProducerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/ProducerImpl.java new file mode 100644 index 0000000000..47ac04fc7d --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/ProducerImpl.java @@ -0,0 +1,208 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.producer; + +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.api.exception.OnExceptionContext; +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.connector.rocketmq.cloudevent.RocketMQMessageFactory; +import org.apache.eventmesh.connector.rocketmq.utils.CloudEventUtils; + +import org.apache.commons.lang3.StringUtils; +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.RequestCallback; +import org.apache.rocketmq.common.MixAll; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageAccessor; +import org.apache.rocketmq.common.message.MessageClientIDSetter; +import org.apache.rocketmq.common.message.MessageConst; +import org.apache.rocketmq.remoting.exception.RemotingException; + +import java.util.Objects; +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@SuppressWarnings("deprecation") +public class ProducerImpl extends AbstractProducer { + + public static final int eventMeshServerAsyncAccumulationThreshold = 1000; + + public ProducerImpl(final Properties properties) { + super(properties); + } + + public Properties attributes() { + return properties; + } + + public void setExtFields() { + super.getRocketmqProducer().setRetryTimesWhenSendFailed(0); + super.getRocketmqProducer().setRetryTimesWhenSendAsyncFailed(0); + super.getRocketmqProducer().setPollNameServerInterval(60000); + + super.getRocketmqProducer().getDefaultMQProducerImpl().getmQClientFactory().getNettyClientConfig() + .setClientAsyncSemaphoreValue(eventMeshServerAsyncAccumulationThreshold); + super.getRocketmqProducer().setCompressMsgBodyOverHowmuch(10); + } + + + public SendResult send(CloudEvent cloudEvent) { + this.checkProducerServiceState(rocketmqProducer.getDefaultMQProducerImpl()); + org.apache.rocketmq.common.message.Message msg = + RocketMQMessageFactory.createWriter(Objects.requireNonNull(cloudEvent.getSubject())).writeBinary(cloudEvent); + supplySysProp(msg, cloudEvent); + String messageId = null; + try { + org.apache.rocketmq.client.producer.SendResult sendResultRmq = this.rocketmqProducer.send(msg); + SendResult sendResult = new SendResult(); + sendResult.setTopic(sendResultRmq.getMessageQueue().getTopic()); + messageId = sendResultRmq.getMsgId(); + sendResult.setMessageId(messageId); + return sendResult; + } catch (Exception e) { + log.error(String.format("Send message Exception, %s", msg), e); + throw this.checkProducerException(msg.getTopic(), messageId, e); + } + } + + + public void sendOneway(CloudEvent cloudEvent) { + this.checkProducerServiceState(this.rocketmqProducer.getDefaultMQProducerImpl()); + org.apache.rocketmq.common.message.Message msg = + RocketMQMessageFactory.createWriter(Objects.requireNonNull(cloudEvent.getSubject())).writeBinary(cloudEvent); + supplySysProp(msg, cloudEvent); + try { + this.rocketmqProducer.sendOneway(msg); + } catch (Exception e) { + log.error(String.format("Send message oneway Exception, %s", msg), e); + throw this.checkProducerException(msg.getTopic(), MessageClientIDSetter.getUniqID(msg), e); + } + } + + + public void sendAsync(CloudEvent cloudEvent, SendCallback sendCallback) { + this.checkProducerServiceState(this.rocketmqProducer.getDefaultMQProducerImpl()); + org.apache.rocketmq.common.message.Message msg = + RocketMQMessageFactory.createWriter(Objects.requireNonNull(cloudEvent.getSubject())).writeBinary(cloudEvent); + msg = supplySysProp(msg, cloudEvent); + try { + this.rocketmqProducer.send(msg, this.sendCallbackConvert(msg, sendCallback)); + } catch (Exception e) { + log.error(String.format("Send message async Exception, %s", msg), e); + throw this.checkProducerException(msg.getTopic(), MessageClientIDSetter.getUniqID(msg), e); + } + } + + public void request(CloudEvent cloudEvent, RequestReplyCallback rrCallback, long timeout) + throws InterruptedException, RemotingException, MQClientException, MQBrokerException { + + this.checkProducerServiceState(this.rocketmqProducer.getDefaultMQProducerImpl()); + org.apache.rocketmq.common.message.Message msg = + RocketMQMessageFactory.createWriter(Objects.requireNonNull(cloudEvent.getSubject())).writeBinary(cloudEvent); + + supplySysProp(msg, cloudEvent); + + rocketmqProducer.request(msg, rrCallbackConvert(msg, rrCallback), timeout); + } + + public void reply(final CloudEvent cloudEvent, final SendCallback sendCallback) { + this.checkProducerServiceState(this.rocketmqProducer.getDefaultMQProducerImpl()); + org.apache.rocketmq.common.message.Message msg = + RocketMQMessageFactory.createWriter(Objects.requireNonNull(cloudEvent.getSubject())).writeBinary(cloudEvent); + MessageAccessor.putProperty(msg, MessageConst.PROPERTY_MESSAGE_TYPE, MixAll.REPLY_MESSAGE_FLAG); + supplySysProp(msg, cloudEvent); + + try { + this.rocketmqProducer.send(msg, this.sendCallbackConvert(msg, sendCallback)); + } catch (Exception e) { + log.error(String.format("Send message async Exception, %s", msg), e); + throw this.checkProducerException(msg.getTopic(), MessageClientIDSetter.getUniqID(msg), e); + } + + } + + private Message supplySysProp(Message msg, CloudEvent cloudEvent) { + for (String sysPropKey : MessageConst.STRING_HASH_SET) { + String ceKey = sysPropKey.toLowerCase().replaceAll("_", Constants.MESSAGE_PROP_SEPARATOR); + if (cloudEvent.getExtension(ceKey) != null && StringUtils.isNotEmpty(cloudEvent.getExtension(ceKey).toString())) { + MessageAccessor.putProperty(msg, sysPropKey, Objects.requireNonNull(cloudEvent.getExtension(ceKey)).toString()); + msg.getProperties().remove(ceKey); + } + } + return msg; + } + + private RequestCallback rrCallbackConvert(final Message message, final RequestReplyCallback rrCallback) { + return new RequestCallback() { + @Override + public void onSuccess(org.apache.rocketmq.common.message.Message message) { + // clean the message property to lowercase + for (String sysPropKey : MessageConst.STRING_HASH_SET) { + if (StringUtils.isNotEmpty(message.getProperty(sysPropKey))) { + String prop = message.getProperty(sysPropKey); + String tmpPropKey = sysPropKey.toLowerCase().replaceAll("_", Constants.MESSAGE_PROP_SEPARATOR); + MessageAccessor.putProperty(message, tmpPropKey, prop); + message.getProperties().remove(sysPropKey); + } + } + CloudEvent event = RocketMQMessageFactory.createReader(message).toEvent(); + rrCallback.onSuccess(event); + } + + @Override + public void onException(Throwable e) { + String topic = message.getTopic(); + ConnectorRuntimeException onsEx = ProducerImpl.this.checkProducerException(topic, null, e); + OnExceptionContext context = new OnExceptionContext(); + context.setTopic(topic); + context.setException(onsEx); + rrCallback.onException(e); + + } + }; + } + + private org.apache.rocketmq.client.producer.SendCallback sendCallbackConvert(final Message message, + final SendCallback sendCallback) { + return new org.apache.rocketmq.client.producer.SendCallback() { + @Override + public void onSuccess(org.apache.rocketmq.client.producer.SendResult sendResult) { + sendCallback.onSuccess(CloudEventUtils.convertSendResult(sendResult)); + } + + @Override + public void onException(Throwable e) { + String topic = message.getTopic(); + ConnectorRuntimeException onsEx = ProducerImpl.this.checkProducerException(topic, null, e); + OnExceptionContext context = new OnExceptionContext(); + context.setTopic(topic); + context.setException(onsEx); + sendCallback.onException(context); + } + }; + } + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/RocketMQProducerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/RocketMQProducerImpl.java new file mode 100644 index 0000000000..1dbca5926f --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/RocketMQProducerImpl.java @@ -0,0 +1,117 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.producer; + +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.producer.Producer; +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.connector.rocketmq.common.EventMeshConstants; +import org.apache.eventmesh.connector.rocketmq.config.ClientConfiguration; + +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.remoting.exception.RemotingException; + +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@SuppressWarnings("deprecation") +public class RocketMQProducerImpl implements Producer { + + private ProducerImpl producer; + + @Override + public synchronized void init(Properties keyValue) { + final ClientConfiguration clientConfiguration = new ClientConfiguration(); + clientConfiguration.init(); + String producerGroup = keyValue.getProperty(Constants.PRODUCER_GROUP); + + String omsNamesrv = clientConfiguration.namesrvAddr; + Properties properties = new Properties(); + properties.put(Constants.ACCESS_POINTS, omsNamesrv); + properties.put(Constants.REGION, Constants.NAMESPACE); + properties.put(Constants.RMQ_PRODUCER_GROUP, producerGroup); + properties.put(Constants.OPERATION_TIMEOUT, 3000); + properties.put(Constants.PRODUCER_ID, producerGroup); + + producer = new ProducerImpl(properties); + + } + + @Override + public boolean isStarted() { + return producer.isStarted(); + } + + @Override + public boolean isClosed() { + return producer.isClosed(); + } + + @Override + public void start() { + producer.start(); + } + + @Override + public synchronized void shutdown() { + producer.shutdown(); + } + + @Override + public void publish(CloudEvent message, SendCallback sendCallback) throws Exception { + producer.sendAsync(message, sendCallback); + } + + @Override + public void request(CloudEvent message, RequestReplyCallback rrCallback, long timeout) + throws InterruptedException, RemotingException, MQClientException, MQBrokerException { + producer.request(message, rrCallback, timeout); + } + + @Override + public boolean reply(final CloudEvent message, final SendCallback sendCallback) throws Exception { + producer.reply(message, sendCallback); + return true; + } + + @Override + public void checkTopicExist(String topic) throws Exception { + this.producer.getRocketmqProducer() + .getDefaultMQProducerImpl() + .getmQClientFactory() + .getMQClientAPIImpl() + .getDefaultTopicRouteInfoFromNameServer(topic, EventMeshConstants.DEFAULT_TIMEOUT_IN_MILLISECONDS); + } + + @Override + public void setExtFields() { + producer.setExtFields(); + } + + + @Override + public void sendOneway(CloudEvent message) { + producer.sendOneway(message); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/utils/BeanUtils.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/utils/BeanUtils.java new file mode 100644 index 0000000000..443ba8d1e7 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/utils/BeanUtils.java @@ -0,0 +1,153 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.utils; + +import org.apache.commons.lang3.StringUtils; +import org.apache.rocketmq.client.log.ClientLogger; +import org.apache.rocketmq.logging.InternalLogger; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; + +public final class BeanUtils { + + private static final InternalLogger LOG = ClientLogger.getLog(); + + /** + * Maps primitive {@code Class}es to their corresponding wrapper {@code Class}. + */ + private static final Map, Class> primitiveWrapperMap = new HashMap<>(); + + static { + primitiveWrapperMap.put(Boolean.TYPE, Boolean.class); + primitiveWrapperMap.put(Byte.TYPE, Byte.class); + primitiveWrapperMap.put(Character.TYPE, Character.class); + primitiveWrapperMap.put(Short.TYPE, Short.class); + primitiveWrapperMap.put(Integer.TYPE, Integer.class); + primitiveWrapperMap.put(Long.TYPE, Long.class); + primitiveWrapperMap.put(Double.TYPE, Double.class); + primitiveWrapperMap.put(Float.TYPE, Float.class); + primitiveWrapperMap.put(Void.TYPE, Void.TYPE); + } + + private static final Map, Class> wrapperMap = new HashMap<>(); + + static { + primitiveWrapperMap.forEach((primitiveClass, wrapperClass) -> { + if (!Objects.equals(wrapperClass, primitiveClass)) { + wrapperMap.put(wrapperClass, primitiveClass); + } + }); + wrapperMap.put(String.class, String.class); + } + + /** + *

Populate the JavaBeans properties of the specified bean, based on + * the specified name/value pairs. This method uses Java reflection APIs + * to identify corresponding "property setter" method names, and deals + * with setter arguments of type String, boolean, + * int, long, float, and + * double.

+ * + *

The particular setter method to be called for each property is + * determined using the usual JavaBeans introspection mechanisms. Thus, + * you may identify custom setter methods using a BeanInfo class that is + * associated with the class of the bean itself. If no such BeanInfo + * class is available, the standard method name conversion ("set" plus + * the capitalized name of the property in question) is used.

+ * + *

NOTE: It is contrary to the JavaBeans Specification + * to have more than one setter method (with different argument + * signatures) for the same property.

+ * + * @param clazz JavaBean class whose properties are being populated + * @param properties Map keyed by property name, with the corresponding (String or String[]) value(s) to be set + * @param Class type + * @return Class instance + */ + public static T populate(final Properties properties, final Class clazz) { + T obj = null; + try { + obj = clazz.getDeclaredConstructor().newInstance(); + return populate(properties, obj); + } catch (Throwable e) { + LOG.warn("Error occurs !", e); + } + return obj; + } + + public static T populate(final Properties properties, final T obj) { + Class clazz = obj.getClass(); + try { + + Set> entries = properties.entrySet(); + for (Map.Entry entry : entries) { + String entryKey = entry.getKey().toString(); + String[] keyGroup = entryKey.split("[\\._]"); + for (int i = 0; i < keyGroup.length; i++) { + keyGroup[i] = keyGroup[i].toLowerCase(); + keyGroup[i] = StringUtils.capitalize(keyGroup[i]); + } + String beanFieldNameWithCapitalization = StringUtils.join(keyGroup); + try { + setProperties(clazz, obj, "set" + beanFieldNameWithCapitalization, entry.getValue()); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { + //ignored... + } + } + } catch (RuntimeException e) { + LOG.warn("Error occurs !", e); + } + return obj; + } + + public static Class getMethodClass(Class clazz, String methodName) { + Method[] methods = clazz.getMethods(); + for (Method method : methods) { + if (method.getName().equalsIgnoreCase(methodName)) { + return method.getParameterTypes()[0]; + } + } + return null; + } + + public static void setProperties(Class clazz, Object obj, String methodName, + Object value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class parameterClass = getMethodClass(clazz, methodName); + Method setterMethod = clazz.getMethod(methodName, parameterClass); + if (parameterClass == Boolean.TYPE) { + setterMethod.invoke(obj, Boolean.valueOf(value.toString())); + } else if (parameterClass == Integer.TYPE) { + setterMethod.invoke(obj, Integer.valueOf(value.toString())); + } else if (parameterClass == Double.TYPE) { + setterMethod.invoke(obj, Double.valueOf(value.toString())); + } else if (parameterClass == Float.TYPE) { + setterMethod.invoke(obj, Float.valueOf(value.toString())); + } else if (parameterClass == Long.TYPE) { + setterMethod.invoke(obj, Long.valueOf(value.toString())); + } else { + setterMethod.invoke(obj, value); + } + } +} + diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/utils/CloudEventUtils.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/utils/CloudEventUtils.java new file mode 100644 index 0000000000..02ce264b10 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/utils/CloudEventUtils.java @@ -0,0 +1,154 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.utils; + +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.common.Constants; + +import org.apache.commons.lang3.StringUtils; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageAccessor; +import org.apache.rocketmq.common.message.MessageConst; +import org.apache.rocketmq.common.message.MessageExt; + +import java.util.Objects; +import java.util.function.BiConsumer; +import java.util.function.Function; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CloudEventUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(CloudEventUtils.class); + + public static SendResult convertSendResult( + org.apache.rocketmq.client.producer.SendResult rmqResult) { + SendResult sendResult = new SendResult(); + sendResult.setTopic(rmqResult.getMessageQueue().getTopic()); + sendResult.setMessageId(rmqResult.getMsgId()); + return sendResult; + } + + + public static Message msgConvert(MessageExt rmqMsg) { + Message message = new Message(); + initProperty(rmqMsg, message, MessageExt::getTopic, Message::setTopic); + initProperty(rmqMsg, message, MessageExt::getKeys, Message::setKeys); + initProperty(rmqMsg, message, MessageExt::getTags, Message::setTags); + if (rmqMsg.getBody() != null) { + message.setBody(rmqMsg.getBody()); + } + rmqMsg.getProperties().forEach((k, v) -> MessageAccessor.putProperty(message, k, v)); + + if (rmqMsg.getMsgId() != null) { + MessageAccessor.putProperty(message, buildCloudEventPropertyKey(Constants.PROPERTY_MESSAGE_MESSAGE_ID), + rmqMsg.getMsgId()); + } + + if (rmqMsg.getTopic() != null) { + MessageAccessor.putProperty(message, buildCloudEventPropertyKey(Constants.PROPERTY_MESSAGE_DESTINATION), + rmqMsg.getTopic()); + } + + // + MessageAccessor.putProperty(message, buildCloudEventPropertyKey(Constants.PROPERTY_MESSAGE_BORN_HOST), + String.valueOf(rmqMsg.getBornHost())); + MessageAccessor.putProperty(message, buildCloudEventPropertyKey(Constants.PROPERTY_MESSAGE_BORN_TIMESTAMP), + String.valueOf(rmqMsg.getBornTimestamp())); + MessageAccessor.putProperty(message, buildCloudEventPropertyKey(Constants.PROPERTY_MESSAGE_STORE_HOST), + String.valueOf(rmqMsg.getStoreHost())); + MessageAccessor.putProperty(message, buildCloudEventPropertyKey(Constants.PROPERTY_MESSAGE_STORE_TIMESTAMP), + String.valueOf(rmqMsg.getStoreTimestamp())); + + //use in manual ack + MessageAccessor.putProperty(message, buildCloudEventPropertyKey(Constants.PROPERTY_MESSAGE_QUEUE_ID), + String.valueOf(rmqMsg.getQueueId())); + MessageAccessor.putProperty(message, buildCloudEventPropertyKey(Constants.PROPERTY_MESSAGE_QUEUE_OFFSET), + String.valueOf(rmqMsg.getQueueOffset())); + + for (String sysPropKey : MessageConst.STRING_HASH_SET) { + if (StringUtils.isNotEmpty(message.getProperty(sysPropKey))) { + String prop = message.getProperty(sysPropKey); + String tmpPropKey = sysPropKey.toLowerCase().replaceAll("_", Constants.MESSAGE_PROP_SEPARATOR); + MessageAccessor.putProperty(message, tmpPropKey, prop); + message.getProperties().remove(sysPropKey); + } + } + + return message; + } + + + private static String buildCloudEventPropertyKey(String propName) { + return propName; + } + + public static org.apache.rocketmq.common.message.MessageExt msgConvertExt(Message message) { + + org.apache.rocketmq.common.message.MessageExt rmqMessageExt = + new org.apache.rocketmq.common.message.MessageExt(); + try { + initProperty(message, rmqMessageExt, Message::getKeys, Message::setKeys); + initProperty(message, rmqMessageExt, Message::getTags, Message::setTags); + + if (message.getBody() != null) { + rmqMessageExt.setBody(message.getBody()); + } + + + //All destinations in RocketMQ use Topic + rmqMessageExt.setTopic(message.getTopic()); + + int queueId = + Integer.parseInt(message.getProperty(buildCloudEventPropertyKey(Constants.PROPERTY_MESSAGE_QUEUE_ID))); + long queueOffset = Long.parseLong( + message.getProperty(buildCloudEventPropertyKey(Constants.PROPERTY_MESSAGE_QUEUE_OFFSET))); + //use in manual ack + rmqMessageExt.setQueueId(queueId); + rmqMessageExt.setQueueOffset(queueOffset); + + message.getProperties().forEach((k, v) -> MessageAccessor.putProperty(rmqMessageExt, k, v)); + } catch (Exception e) { + LOGGER.error("Error with msgConvertExt", e); + e.printStackTrace(); + } + return rmqMessageExt; + + } + + /** + * Populate the target with properties whose source is not empty + * + * @param source source + * @param target target + * @param function function + * @param biConsumer biConsumer + * @param t + * @param v + */ + private static void initProperty(T source, V target, Function function, BiConsumer biConsumer) { + String apply = function.apply(source); + if (Objects.nonNull(apply)) { + biConsumer.accept(target, apply); + } + + } + + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/utils/OMSUtil.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/utils/OMSUtil.java new file mode 100644 index 0000000000..f42e640321 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/utils/OMSUtil.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.utils; + +import org.apache.rocketmq.common.UtilAll; + +public class OMSUtil { + + /** + * Builds a OMS client instance name. + * + * @return a unique instance name + */ + public static String buildInstanceName() { + return UtilAll.getPid() + "%EventMesh" + "%" + System.nanoTime(); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyService.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyService.java new file mode 100644 index 0000000000..9d5f408c28 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyService.java @@ -0,0 +1,503 @@ +/* + * 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. + */ + +package org.apache.rocketmq.client.impl.consumer; + +import org.apache.eventmesh.connector.rocketmq.patch.EventMeshConsumeConcurrentlyContext; + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.ConsumeReturnType; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.hook.ConsumeMessageContext; +import org.apache.rocketmq.client.log.ClientLogger; +import org.apache.rocketmq.client.stat.ConsumerStatsManager; +import org.apache.rocketmq.common.MixAll; +import org.apache.rocketmq.common.ThreadFactoryImpl; +import org.apache.rocketmq.common.message.MessageAccessor; +import org.apache.rocketmq.common.message.MessageConst; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.common.message.MessageQueue; +import org.apache.rocketmq.common.protocol.body.CMResult; +import org.apache.rocketmq.common.protocol.body.ConsumeMessageDirectlyResult; +import org.apache.rocketmq.logging.InternalLogger; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class ConsumeMessageConcurrentlyService implements ConsumeMessageService { + private static final InternalLogger log = ClientLogger.getLog(); + private final DefaultMQPushConsumerImpl defaultMQPushConsumerImpl; + private final DefaultMQPushConsumer defaultMQPushConsumer; + private final MessageListenerConcurrently messageListener; + private final BlockingQueue consumeRequestQueue; + private final ThreadPoolExecutor consumeExecutor; + private final String consumerGroup; + + static { + log.info("load custom ConsumeMessageConcurrentlyService class for eventMesh, because of updateOffset"); + } + + private final ScheduledExecutorService scheduledExecutorService; + private final ScheduledExecutorService cleanExpireMsgExecutors; + + public ConsumeMessageConcurrentlyService(DefaultMQPushConsumerImpl defaultMQPushConsumerImpl, + MessageListenerConcurrently messageListener) { + this.defaultMQPushConsumerImpl = defaultMQPushConsumerImpl; + this.messageListener = messageListener; + + this.defaultMQPushConsumer = this.defaultMQPushConsumerImpl.getDefaultMQPushConsumer(); + this.consumerGroup = this.defaultMQPushConsumer.getConsumerGroup(); + this.consumeRequestQueue = new LinkedBlockingQueue(); + + this.consumeExecutor = new ThreadPoolExecutor( + this.defaultMQPushConsumer.getConsumeThreadMin(), + this.defaultMQPushConsumer.getConsumeThreadMax(), + 1000 * 60, + TimeUnit.MILLISECONDS, + this.consumeRequestQueue, + new ThreadFactoryImpl("ConsumeMessageThread_" + consumerGroup + "_")); + + this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl("ConsumeMessageScheduledThread_")); + this.cleanExpireMsgExecutors = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl("CleanExpireMsgScheduledThread_")); + + log.info("new ConsumeMessageConcurrentlyService instance for eventMesh has been created "); + } + + public void start() { + if (this.defaultMQPushConsumer.getConsumeTimeout() > 0) { + this.cleanExpireMsgExecutors.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + cleanExpireMsg(); + } catch (Exception e) { + log.warn("cleanExpireMsg ", e); + } + } + + }, this.defaultMQPushConsumer.getConsumeTimeout(), this.defaultMQPushConsumer.getConsumeTimeout(), TimeUnit.MINUTES); + } + } + + @Override + public void shutdown(long awaitTerminateMillis) { + + } + + public void shutdown() { + this.scheduledExecutorService.shutdown(); + this.consumeExecutor.shutdown(); + this.cleanExpireMsgExecutors.shutdown(); + } + + public ThreadPoolExecutor getConsumeExecutor() { + return consumeExecutor; + } + + @Override + public void updateCorePoolSize(int corePoolSize) { + if (corePoolSize > 0 + && corePoolSize <= Short.MAX_VALUE + && corePoolSize < this.defaultMQPushConsumer.getConsumeThreadMax()) { + this.consumeExecutor.setCorePoolSize(corePoolSize); + } + } + + @Override + public void incCorePoolSize() { + } + + @Override + public void decCorePoolSize() { + } + + @Override + public int getCorePoolSize() { + return this.consumeExecutor.getCorePoolSize(); + } + + @Override + public ConsumeMessageDirectlyResult consumeMessageDirectly(MessageExt msg, String brokerName) { + ConsumeMessageDirectlyResult result = new ConsumeMessageDirectlyResult(); + result.setOrder(false); + result.setAutoCommit(true); + + List msgs = new ArrayList(); + msgs.add(msg); + MessageQueue mq = new MessageQueue(); + mq.setTopic(msg.getTopic()); + mq.setQueueId(msg.getQueueId()); + + ProcessQueue pq = new ProcessQueue(); + EventMeshConsumeConcurrentlyContext context = new EventMeshConsumeConcurrentlyContext(mq, pq); + + this.resetRetryTopic(msgs); + + final long beginTime = System.currentTimeMillis(); + + log.info("consumeMessageDirectly receive new message: {}", msg); + + try { + ConsumeConcurrentlyStatus status = this.messageListener.consumeMessage(msgs, context); + if (status != null) { + switch (status) { + case CONSUME_SUCCESS: + result.setConsumeResult(CMResult.CR_SUCCESS); + break; + case RECONSUME_LATER: + result.setConsumeResult(CMResult.CR_LATER); + break; + default: + break; + } + } else { + result.setConsumeResult(CMResult.CR_RETURN_NULL); + } + } catch (Throwable e) { + result.setConsumeResult(CMResult.CR_THROW_EXCEPTION); + result.setRemark(RemotingHelper.exceptionSimpleDesc(e)); + + log.warn(String.format("consumeMessageDirectly exception: %s Group: %s Msgs: %s MQ: %s", + RemotingHelper.exceptionSimpleDesc(e), + ConsumeMessageConcurrentlyService.this.consumerGroup, + msgs, + mq), e); + } + + result.setSpentTimeMills(System.currentTimeMillis() - beginTime); + + log.info("consumeMessageDirectly Result: {}", result); + + return result; + } + + @Override + public void submitConsumeRequest( + final List msgs, + final ProcessQueue processQueue, + final MessageQueue messageQueue, + final boolean dispatchToConsume) { + final int consumeBatchSize = this.defaultMQPushConsumer.getConsumeMessageBatchMaxSize(); + if (msgs.size() <= consumeBatchSize) { + ConsumeRequest consumeRequest = new ConsumeRequest(msgs, processQueue, messageQueue); + try { + this.consumeExecutor.submit(consumeRequest); + } catch (RejectedExecutionException e) { + this.submitConsumeRequestLater(consumeRequest); + } + } else { + for (int total = 0; total < msgs.size(); ) { + List msgThis = new ArrayList(consumeBatchSize); + for (int i = 0; i < consumeBatchSize; i++, total++) { + if (total < msgs.size()) { + msgThis.add(msgs.get(total)); + } else { + break; + } + } + + ConsumeRequest consumeRequest = new ConsumeRequest(msgThis, processQueue, messageQueue); + try { + this.consumeExecutor.submit(consumeRequest); + } catch (RejectedExecutionException e) { + for (; total < msgs.size(); total++) { + msgThis.add(msgs.get(total)); + } + + this.submitConsumeRequestLater(consumeRequest); + } + } + } + } + + public void resetRetryTopic(final List msgs) { + final String groupTopic = MixAll.getRetryTopic(consumerGroup); + for (MessageExt msg : msgs) { + String retryTopic = msg.getProperty(MessageConst.PROPERTY_RETRY_TOPIC); + if (retryTopic != null && groupTopic.equals(msg.getTopic())) { + msg.setTopic(retryTopic); + } + } + } + + private void cleanExpireMsg() { + this.defaultMQPushConsumerImpl.getRebalanceImpl().getProcessQueueTable().forEach((k, pq) -> { + pq.cleanExpiredMsg(this.defaultMQPushConsumer); + }); + } + + public void processConsumeResult( + final ConsumeConcurrentlyStatus status, + final EventMeshConsumeConcurrentlyContext context, + final ConsumeRequest consumeRequest) { + int ackIndex = context.getAckIndex(); + + if (consumeRequest.getMsgs().isEmpty()) { + return; + } + + switch (status) { + case CONSUME_SUCCESS: + if (ackIndex >= consumeRequest.getMsgs().size()) { + ackIndex = consumeRequest.getMsgs().size() - 1; + } + int ok = ackIndex + 1; + int failed = consumeRequest.getMsgs().size() - ok; + this.getConsumerStatsManager().incConsumeOKTPS(consumerGroup, consumeRequest.getMessageQueue().getTopic(), ok); + this.getConsumerStatsManager().incConsumeFailedTPS(consumerGroup, consumeRequest.getMessageQueue().getTopic(), failed); + break; + case RECONSUME_LATER: + ackIndex = -1; + this.getConsumerStatsManager().incConsumeFailedTPS(consumerGroup, consumeRequest.getMessageQueue().getTopic(), + consumeRequest.getMsgs().size()); + break; + default: + break; + } + + switch (this.defaultMQPushConsumer.getMessageModel()) { + case BROADCASTING: + for (int i = ackIndex + 1; i < consumeRequest.getMsgs().size(); i++) { + MessageExt msg = consumeRequest.getMsgs().get(i); + log.warn("BROADCASTING, the message consume failed, drop it, {}", msg.toString()); + } + break; + case CLUSTERING: + List msgBackFailed = new ArrayList(consumeRequest.getMsgs().size()); + for (int i = ackIndex + 1; i < consumeRequest.getMsgs().size(); i++) { + MessageExt msg = consumeRequest.getMsgs().get(i); + boolean result = this.sendMessageBack(msg, context); + if (!result) { + msg.setReconsumeTimes(msg.getReconsumeTimes() + 1); + msgBackFailed.add(msg); + } + } + + if (!msgBackFailed.isEmpty()) { + consumeRequest.getMsgs().removeAll(msgBackFailed); + + this.submitConsumeRequestLater(msgBackFailed, consumeRequest.getProcessQueue(), consumeRequest.getMessageQueue()); + } + break; + default: + break; + } + if (!context.isManualAck()) { + updateOffset(consumeRequest.getMsgs(), context); + } + } + + public void updateOffset(List msgs, ConsumeConcurrentlyContext context) { + for (MessageExt m : msgs) { + log.debug("update offset, msg: {} {} {}", m.getTopic(), m.getQueueId(), m.getQueueOffset()); + } + MessageQueue messageQueue = context.getMessageQueue(); + ProcessQueue processQueue = ((EventMeshConsumeConcurrentlyContext) context).getProcessQueue(); + long offset = processQueue.removeMessage(msgs); + if (offset >= 0) { + log.debug("update offset={}", offset); + this.defaultMQPushConsumerImpl.getOffsetStore().updateOffset(messageQueue, offset, true); + } + } + + + public ConsumerStatsManager getConsumerStatsManager() { + return this.defaultMQPushConsumerImpl.getConsumerStatsManager(); + } + + public boolean sendMessageBack(final MessageExt msg, final ConsumeConcurrentlyContext context) { + int delayLevel = context.getDelayLevelWhenNextConsume(); + + try { + this.defaultMQPushConsumerImpl.sendMessageBack(msg, delayLevel, context.getMessageQueue().getBrokerName()); + return true; + } catch (Exception e) { + log.error("sendMessageBack exception, group: {}" + " msg: {}", this.consumerGroup, msg, e); + } + + return false; + } + + private void submitConsumeRequestLater( + final List msgs, + final ProcessQueue processQueue, + final MessageQueue messageQueue + ) { + + this.scheduledExecutorService.schedule(new Runnable() { + + @Override + public void run() { + ConsumeMessageConcurrentlyService.this.submitConsumeRequest(msgs, processQueue, messageQueue, true); + } + }, 5000, TimeUnit.MILLISECONDS); + } + + private void submitConsumeRequestLater(final ConsumeRequest consumeRequest) { + final int times = defaultMQPushConsumerImpl.getDefaultMQPushConsumer().getMaxReconsumeTimes(); + log.warn("rejected by thread pool, try resubmit {} times, consumerGroup:{}", times, + defaultMQPushConsumerImpl.getDefaultMQPushConsumer().getConsumerGroup()); + this.scheduledExecutorService.schedule(new Runnable() { + + @Override + public void run() { + boolean success = false; + for (int i = 0; i < times; i++) { + try { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + //ignore + } + ConsumeMessageConcurrentlyService.this.consumeExecutor.submit(consumeRequest); + success = true; + break; + } catch (RejectedExecutionException e) { + //ignore + } + } + if (!success) { + for (MessageExt messageExt : consumeRequest.getMsgs()) { + log.warn("discard rejected messages {} after retry {} times", messageExt, times); + } + consumeRequest.getProcessQueue().removeMessage(consumeRequest.getMsgs()); + } + } + }, 1000, TimeUnit.MILLISECONDS); + } + + class ConsumeRequest implements Runnable { + private final List msgs; + private final ProcessQueue processQueue; + private final MessageQueue messageQueue; + + public ConsumeRequest(List msgs, ProcessQueue processQueue, MessageQueue messageQueue) { + this.msgs = msgs; + this.processQueue = processQueue; + this.messageQueue = messageQueue; + } + + public List getMsgs() { + return msgs; + } + + public ProcessQueue getProcessQueue() { + return processQueue; + } + + @Override + public void run() { + if (this.processQueue.isDropped()) { + log.info("the message queue not be able to consume, because it's dropped. group={} {}", + ConsumeMessageConcurrentlyService.this.consumerGroup, this.messageQueue); + return; + } + + MessageListenerConcurrently listener = ConsumeMessageConcurrentlyService.this.messageListener; + EventMeshConsumeConcurrentlyContext context = new EventMeshConsumeConcurrentlyContext(messageQueue, processQueue); + ConsumeConcurrentlyStatus status = null; + + ConsumeMessageContext consumeMessageContext = null; + if (ConsumeMessageConcurrentlyService.this.defaultMQPushConsumerImpl.hasHook()) { + consumeMessageContext = new ConsumeMessageContext(); + consumeMessageContext.setConsumerGroup(defaultMQPushConsumer.getConsumerGroup()); + consumeMessageContext.setProps(new HashMap()); + consumeMessageContext.setMq(messageQueue); + consumeMessageContext.setMsgList(msgs); + consumeMessageContext.setSuccess(false); + ConsumeMessageConcurrentlyService.this.defaultMQPushConsumerImpl.executeHookBefore(consumeMessageContext); + } + + long beginTimestamp = System.currentTimeMillis(); + boolean hasException = false; + ConsumeReturnType returnType = ConsumeReturnType.SUCCESS; + try { + ConsumeMessageConcurrentlyService.this.resetRetryTopic(msgs); + if (!msgs.isEmpty()) { + for (MessageExt msg : msgs) { + MessageAccessor.setConsumeStartTimeStamp(msg, String.valueOf(System.currentTimeMillis())); + } + + + } + status = listener.consumeMessage(Collections.unmodifiableList(msgs), context); + } catch (Throwable e) { + log.warn("consumeMessage exception: {} Group: {} Msgs: {} MQ: {}", + RemotingHelper.exceptionSimpleDesc(e), + ConsumeMessageConcurrentlyService.this.consumerGroup, + msgs, + messageQueue); + hasException = true; + } + long consumeRT = System.currentTimeMillis() - beginTimestamp; + if (null == status) { + if (hasException) { + returnType = ConsumeReturnType.EXCEPTION; + } else { + returnType = ConsumeReturnType.RETURNNULL; + } + } else if (consumeRT >= defaultMQPushConsumer.getConsumeTimeout() * 60 * 1000) { + returnType = ConsumeReturnType.TIME_OUT; + } else if (ConsumeConcurrentlyStatus.RECONSUME_LATER == status) { + returnType = ConsumeReturnType.FAILED; + } else if (ConsumeConcurrentlyStatus.CONSUME_SUCCESS == status) { + returnType = ConsumeReturnType.SUCCESS; + } + + if (ConsumeMessageConcurrentlyService.this.defaultMQPushConsumerImpl.hasHook()) { + consumeMessageContext.getProps().put(MixAll.CONSUME_CONTEXT_TYPE, returnType.name()); + } + + if (null == status) { + log.warn("consumeMessage return null, Group: {} Msgs: {} MQ: {}", + ConsumeMessageConcurrentlyService.this.consumerGroup, + msgs, + messageQueue); + status = ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + + if (ConsumeMessageConcurrentlyService.this.defaultMQPushConsumerImpl.hasHook()) { + consumeMessageContext.setStatus(status.toString()); + consumeMessageContext.setSuccess(ConsumeConcurrentlyStatus.CONSUME_SUCCESS == status); + ConsumeMessageConcurrentlyService.this.defaultMQPushConsumerImpl.executeHookAfter(consumeMessageContext); + } + + ConsumeMessageConcurrentlyService.this.getConsumerStatsManager() + .incConsumeRT(ConsumeMessageConcurrentlyService.this.consumerGroup, messageQueue.getTopic(), consumeRT); + + ConsumeMessageConcurrentlyService.this.processConsumeResult(status, context, this); + } + + public MessageQueue getMessageQueue() { + return messageQueue; + } + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.admin.Admin b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.admin.Admin new file mode 100644 index 0000000000..c76b692524 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.admin.Admin @@ -0,0 +1,16 @@ +# 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. + +rocketmq=org.apache.eventmesh.connector.rocketmq.admin.RocketMQAdminAdaptor \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService new file mode 100644 index 0000000000..fadf0de344 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService @@ -0,0 +1,16 @@ +# 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. + +rocketmq=org.apache.eventmesh.connector.rocketmq.connector.ConnectorResourceServiceRocketmqImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer new file mode 100644 index 0000000000..0df2e286d7 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer @@ -0,0 +1,16 @@ +# 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. + +rocketmq=org.apache.eventmesh.connector.rocketmq.consumer.RocketMQConsumerImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer new file mode 100644 index 0000000000..ef4959d994 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer @@ -0,0 +1,16 @@ +# 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. + +rocketmq=org.apache.eventmesh.connector.rocketmq.producer.RocketMQProducerImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/rocketmq-client.properties b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/rocketmq-client.properties new file mode 100644 index 0000000000..8e0822ad36 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/resources/rocketmq-client.properties @@ -0,0 +1,21 @@ +# +# 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. +# +#######################rocketmq-client################## +eventMesh.server.rocketmq.namesrvAddr=127.0.0.1:9876;127.0.0.1:9876 +eventMesh.server.rocketmq.cluster=DefaultCluster +eventMesh.server.rocketmq.accessKey=******** +eventMesh.server.rocketmq.secretKey=******** diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/eventmesh/connector/rocketmq/config/ConfigurationWrapperTest.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/eventmesh/connector/rocketmq/config/ConfigurationWrapperTest.java new file mode 100644 index 0000000000..6d25baf7cf --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/eventmesh/connector/rocketmq/config/ConfigurationWrapperTest.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.rocketmq.config; + +import org.junit.Assert; +import org.junit.Test; + +public class ConfigurationWrapperTest { + + @Test + public void getProp() { + String namesrcAddr = ConfigurationWrapper.getProp("eventMesh.server.rocketmq.namesrvAddr"); + Assert.assertNotNull(namesrcAddr); + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/eventmesh/producer/DefaultProducerImplTest.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/eventmesh/producer/DefaultProducerImplTest.java new file mode 100644 index 0000000000..3114c54f0e --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/eventmesh/producer/DefaultProducerImplTest.java @@ -0,0 +1,56 @@ +/* + * 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. + */ + +package org.apache.eventmesh.producer; + + +import org.junit.After; +import org.junit.Before; + +public class DefaultProducerImplTest { + + @Before + public void before() { + } + + + @After + public void after() { + //TBD:Remove topic + } + + //@Test + //public void testCreate_EmptyTopic() { + // MeshMQProducer meshPub = new RocketMQProducerImpl(); + // try { + // meshPub.createTopic(" "); + // } catch (OMSRuntimeException e) { + // assertThat(e.getMessage()).isEqualToIgnoringWhitespace("RocketMQ can not create topic"); + // } + //} + // + //@Test + //public void testCreate_NullTopic() { + // MeshMQProducer meshPub = new RocketMQProducerImpl(); + // try { + // meshPub.createTopic(null); + // } catch (OMSRuntimeException e) { + // String errorMessage = e.getMessage(); + // assertThat(errorMessage).isEqualTo("RocketMQ can not create topic null"); + // } + //} +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/rocketmq/consumer/PushConsumerImplTest.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/rocketmq/consumer/PushConsumerImplTest.java new file mode 100644 index 0000000000..ada76860ea --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/rocketmq/consumer/PushConsumerImplTest.java @@ -0,0 +1,98 @@ +/* + * 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. + */ + +package org.apache.rocketmq.consumer; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.connector.rocketmq.consumer.PushConsumerImpl; +import org.apache.eventmesh.connector.rocketmq.domain.NonStandardKeys; + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.common.message.MessageExt; + +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import io.cloudevents.CloudEvent; + +@RunWith(MockitoJUnitRunner.class) +public class PushConsumerImplTest { + private PushConsumerImpl consumer; + + @Mock + private DefaultMQPushConsumer rocketmqPushConsumer; + + @Before + public void before() throws Exception { + Properties consumerProp = new Properties(); + //consumerProp.setProperty(OMSBuiltinKeys.DRIVER_IMPL, + // "org.apache.eventmesh.connector.rocketmq.MessagingAccessPointImpl"); + consumerProp.setProperty("access_points", "IP1:9876,IP2:9876"); + //final MessagingAccessPoint messagingAccessPoint = OMS.builder().build(consumerProp); + // .endpoint("oms:rocketmq://IP1:9876,IP2:9876/namespace").build(config); + + consumerProp.setProperty("message.model", "CLUSTERING"); + + //Properties consumerProp = new Properties(); + consumerProp.put("CONSUMER_ID", "TestGroup"); + consumer = new PushConsumerImpl(consumerProp); + + + Field field = PushConsumerImpl.class.getDeclaredField("rocketmqPushConsumer"); + field.setAccessible(true); + DefaultMQPushConsumer innerConsumer = (DefaultMQPushConsumer) field.get(consumer); + field.set(consumer, rocketmqPushConsumer); //Replace + + Mockito.when(rocketmqPushConsumer.getMessageListener()).thenReturn(innerConsumer.getMessageListener()); + consumer.start(); + } + + @After + public void after() throws Exception { + Mockito.verify(rocketmqPushConsumer).getMessageListener(); + consumer.shutdown(); + } + + @Test + public void testConsumeMessage() { + final byte[] testBody = new byte[] {'a', 'b'}; + + MessageExt consumedMsg = new MessageExt(); + consumedMsg.setMsgId("NewMsgId"); + consumedMsg.setBody(testBody); + consumedMsg.putUserProperty(NonStandardKeys.MESSAGE_DESTINATION, "TOPIC"); + consumedMsg.setTopic("HELLO_QUEUE"); + consumer.subscribe("HELLO_QUEUE", "*"); + ((MessageListenerConcurrently) rocketmqPushConsumer + .getMessageListener()).consumeMessage(Collections.singletonList(consumedMsg), null); + + + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/rocketmq/producer/ProducerImplTest.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/rocketmq/producer/ProducerImplTest.java new file mode 100644 index 0000000000..04d3a29001 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/rocketmq/producer/ProducerImplTest.java @@ -0,0 +1,139 @@ +/* + * 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. + */ + +package org.apache.rocketmq.producer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Fail.failBecauseExceptionWasNotThrown; +import static org.mockito.ArgumentMatchers.any; + +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.common.Constants; +import org.apache.eventmesh.connector.rocketmq.producer.AbstractProducer; +import org.apache.eventmesh.connector.rocketmq.producer.ProducerImpl; + +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.client.producer.SendStatus; +import org.apache.rocketmq.common.ServiceState; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageQueue; +import org.apache.rocketmq.remoting.exception.RemotingException; + +import java.lang.reflect.Field; +import java.net.URI; +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; + +@RunWith(MockitoJUnitRunner.class) +public class ProducerImplTest { + private ProducerImpl producer; + + @Mock + private DefaultMQProducer rocketmqProducer; + + @Before + public void before() throws NoSuchFieldException, IllegalAccessException { + Properties config = new Properties(); + config.setProperty("access_points", "IP1:9876,IP2:9876"); + producer = new ProducerImpl(config); + + Field field = AbstractProducer.class.getDeclaredField("rocketmqProducer"); + field.setAccessible(true); + field.set(producer, rocketmqProducer); + + producer.start(); + + } + + @After + public void after() { + producer.shutdown(); + } + + @Test + public void testSend_OK() throws InterruptedException, RemotingException, MQClientException, MQBrokerException { + SendResult sendResult = new SendResult(); + sendResult.setMsgId("TestMsgID"); + sendResult.setSendStatus(SendStatus.SEND_OK); + MessageQueue messageQueue = new MessageQueue("HELLO_TOPIC", "testBroker", 0); + sendResult.setMessageQueue(messageQueue); + + Mockito.when(rocketmqProducer.send(any(Message.class))).thenReturn(sendResult); + + DefaultMQProducer defaultMQProducer = new DefaultMQProducer("testGroup"); + DefaultMQProducerImpl defaultMQProducerImpl = new DefaultMQProducerImpl(defaultMQProducer); + defaultMQProducerImpl.setServiceState(ServiceState.RUNNING); + Mockito.when(rocketmqProducer.getDefaultMQProducerImpl()).thenReturn(defaultMQProducerImpl); + + + CloudEvent cloudEvent = CloudEventBuilder.v1() + .withId("id1") + .withSource(URI.create("https://github.com/cloudevents/*****")) + .withType("producer.example") + .withSubject("HELLO_TOPIC") + .withData("hello world".getBytes(Constants.DEFAULT_CHARSET)) + .build(); + org.apache.eventmesh.api.SendResult result = + producer.send(cloudEvent); + + assertThat(result.getMessageId()).isEqualTo("TestMsgID"); + Mockito.verify(rocketmqProducer).getDefaultMQProducerImpl(); + Mockito.verify(rocketmqProducer).send(any(Message.class)); + + } + + @Test + public void testSend_WithException() throws InterruptedException, RemotingException, MQClientException, MQBrokerException { + DefaultMQProducer defaultMQProducer = new DefaultMQProducer("testGroup"); + DefaultMQProducerImpl defaultMQProducerImpl = new DefaultMQProducerImpl(defaultMQProducer); + defaultMQProducerImpl.setServiceState(ServiceState.RUNNING); + Mockito.when(rocketmqProducer.getDefaultMQProducerImpl()).thenReturn(defaultMQProducerImpl); + MQClientException exception = new MQClientException("Send message to RocketMQ broker failed.", new Exception()); + Mockito.when(rocketmqProducer.send(any(Message.class))).thenThrow(exception); + + try { + CloudEvent cloudEvent = CloudEventBuilder.v1() + .withId("id1") + .withSource(URI.create("https://github.com/cloudevents/*****")) + .withType("producer.example") + .withSubject("HELLO_TOPIC") + .withData(new byte[]{'a'}) + .build(); + producer.send(cloudEvent); + failBecauseExceptionWasNotThrown(ConnectorRuntimeException.class); + } catch (Exception e) { + assertThat(e).hasMessageContaining("Send message to RocketMQ broker failed."); + } + + Mockito.verify(rocketmqProducer).send(any(Message.class)); + } + +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/rocketmq/promise/DefaultPromiseTest.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/rocketmq/promise/DefaultPromiseTest.java new file mode 100644 index 0000000000..3d4c8c2ab3 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/rocketmq/promise/DefaultPromiseTest.java @@ -0,0 +1,121 @@ +///* +// * 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. +// */ +//package rocketmq.promise; +// +//import org.apache.eventmesh.connector.rocketmq.promise.DefaultPromise; +//import io.openmessaging.Future; +//import io.openmessaging.FutureListener; +//import io.openmessaging.Promise; +//import io.openmessaging.exception.OMSRuntimeException; +//import org.junit.Before; +//import org.junit.Test; +// +//import static org.assertj.core.api.Assertions.assertThat; +//import static org.assertj.core.api.Fail.failBecauseExceptionWasNotThrown; +// +//public class DefaultPromiseTest { +// private Promise promise; +// +// @Before +// public void init() { +// promise = new DefaultPromise<>(); +// } +// +// @Test +// public void testIsCancelled() throws Exception { +// assertThat(promise.isCancelled()).isEqualTo(false); +// } +// +// @Test +// public void testIsDone() throws Exception { +// assertThat(promise.isDone()).isEqualTo(false); +// promise.set("Done"); +// assertThat(promise.isDone()).isEqualTo(true); +// } +// +// @Test +// public void testGet() throws Exception { +// promise.set("Done"); +// assertThat(promise.get()).isEqualTo("Done"); +// } +// +// @Test +// public void testGet_WithTimeout() throws Exception { +// try { +// promise.get(100); +// failBecauseExceptionWasNotThrown(OMSRuntimeException.class); +// } catch (OMSRuntimeException e) { +// assertThat(e).hasMessageContaining("Get request result is timeout or interrupted"); +// } +// } +// +// @Test +// public void testAddListener() throws Exception { +// promise.addListener(new FutureListener() { +// @Override +// public void operationComplete(Future future) { +// assertThat(promise.get()).isEqualTo("Done"); +// +// } +// }); +// promise.set("Done"); +// } +// +// @Test +// public void testAddListener_ListenerAfterSet() throws Exception { +// promise.set("Done"); +// promise.addListener(new FutureListener() { +// @Override +// public void operationComplete(Future future) { +// assertThat(future.get()).isEqualTo("Done"); +// } +// }); +// } +// +// @Test +// public void testAddListener_WithException_ListenerAfterSet() throws Exception { +// final Throwable exception = new OMSRuntimeException("-1", "Test Error"); +// promise.setFailure(exception); +// promise.addListener(new FutureListener() { +// @Override +// public void operationComplete(Future future) { +// assertThat(promise.getThrowable()).isEqualTo(exception); +// } +// }); +// } +// +// @Test +// public void testAddListener_WithException() throws Exception { +// final Throwable exception = new OMSRuntimeException("-1", "Test Error"); +// promise.addListener(new FutureListener() { +// @Override +// public void operationComplete(Future future) { +// assertThat(promise.getThrowable()).isEqualTo(exception); +// } +// }); +// promise.setFailure(exception); +// } +// +// @Test +// public void getThrowable() throws Exception { +// assertThat(promise.getThrowable()).isNull(); +// Throwable exception = new OMSRuntimeException("-1", "Test Error"); +// promise.setFailure(exception); +// assertThat(promise.getThrowable()).isEqualTo(exception); +// } +// +//} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/rocketmq/utils/BeanUtilsTest.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/rocketmq/utils/BeanUtilsTest.java new file mode 100644 index 0000000000..1a7f52c0e5 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/java/org/apache/rocketmq/utils/BeanUtilsTest.java @@ -0,0 +1,113 @@ +/* + * 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. + */ + +package org.apache.rocketmq.utils; + +import org.apache.eventmesh.connector.rocketmq.config.ClientConfig; +import org.apache.eventmesh.connector.rocketmq.domain.NonStandardKeys; +import org.apache.eventmesh.connector.rocketmq.utils.BeanUtils; + +import java.util.Properties; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class BeanUtilsTest { + private Properties properties = new Properties(); + + public static class CustomizedConfig extends ClientConfig { + static final String STRING_TEST = "string.test"; + String stringTest = "foobar"; + + static final String DOUBLE_TEST = "double.test"; + double doubleTest = 123.0; + + static final String LONG_TEST = "long.test"; + long longTest = 123L; + + String getStringTest() { + return stringTest; + } + + public void setStringTest(String stringTest) { + this.stringTest = stringTest; + } + + double getDoubleTest() { + return doubleTest; + } + + public void setDoubleTest(final double doubleTest) { + this.doubleTest = doubleTest; + } + + long getLongTest() { + return longTest; + } + + public void setLongTest(final long longTest) { + this.longTest = longTest; + } + + public CustomizedConfig() { + } + } + + @Before + public void before() { + properties.put(NonStandardKeys.MAX_REDELIVERY_TIMES, 120); + properties.put(CustomizedConfig.STRING_TEST, "kaka"); + properties.put(NonStandardKeys.CONSUMER_GROUP, "Default_Consumer_Group"); + properties.put(NonStandardKeys.MESSAGE_CONSUME_TIMEOUT, 101); + + properties.put(CustomizedConfig.LONG_TEST, 1234567890L); + properties.put(CustomizedConfig.DOUBLE_TEST, 10.234); + } + + @Test + public void testPopulate() { + CustomizedConfig config = BeanUtils.populate(properties, CustomizedConfig.class); + + //RemotingConfig config = BeanUtils.populate(properties, RemotingConfig.class); + Assert.assertEquals(config.getRmqMaxRedeliveryTimes(), 120); + Assert.assertEquals(config.getStringTest(), "kaka"); + Assert.assertEquals(config.getRmqConsumerGroup(), "Default_Consumer_Group"); + Assert.assertEquals(config.getRmqMessageConsumeTimeout(), 101); + Assert.assertEquals(config.getLongTest(), 1234567890L); + Assert.assertEquals(config.getDoubleTest(), 10.234, 0.000001); + } + + @Test + public void testPopulate_ExistObj() { + CustomizedConfig config = new CustomizedConfig(); + config.setConsumerId("NewConsumerId"); + + Assert.assertEquals(config.getConsumerId(), "NewConsumerId"); + + config = BeanUtils.populate(properties, config); + + //RemotingConfig config = BeanUtils.populate(properties, RemotingConfig.class); + Assert.assertEquals(config.getRmqMaxRedeliveryTimes(), 120); + Assert.assertEquals(config.getStringTest(), "kaka"); + Assert.assertEquals(config.getRmqConsumerGroup(), "Default_Consumer_Group"); + Assert.assertEquals(config.getRmqMessageConsumeTimeout(), 101); + Assert.assertEquals(config.getLongTest(), 1234567890L); + Assert.assertEquals(config.getDoubleTest(), 10.234, 0.000001); + } + +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/resources/META-INF/services/org.apache.io.openmessaging.producer.Producer b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/resources/META-INF/services/org.apache.io.openmessaging.producer.Producer new file mode 100644 index 0000000000..bf0a8ddc29 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/resources/META-INF/services/org.apache.io.openmessaging.producer.Producer @@ -0,0 +1,20 @@ +# +# 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. +# + +org.apache.eventmesh.connector.rocketmq.producer.ProducerImpl \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/resources/rocketmq-client.properties b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/resources/rocketmq-client.properties new file mode 100644 index 0000000000..1261f30e2c --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/test/resources/rocketmq-client.properties @@ -0,0 +1,18 @@ +# +# 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. +# +#######################rocketmq-client################## +eventMesh.server.rocketmq.namesrvAddr=127.0.0.1:9876;127.0.0.1:9876 diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/build.gradle b/eventmesh-connector-plugin/eventmesh-connector-standalone/build.gradle new file mode 100644 index 0000000000..51510087fa --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/build.gradle @@ -0,0 +1,21 @@ +/* + * 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. + */ + +dependencies { + implementation project(":eventmesh-common") + implementation project(":eventmesh-connector-plugin:eventmesh-connector-api") +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/gradle.properties b/eventmesh-connector-plugin/eventmesh-connector-standalone/gradle.properties new file mode 100644 index 0000000000..d2e986bcd9 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/gradle.properties @@ -0,0 +1,17 @@ +# 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. +# +pluginType=connector +pluginName=standalone \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/admin/StandaloneAdmin.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/admin/StandaloneAdmin.java new file mode 100644 index 0000000000..9c5e1bc485 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/admin/StandaloneAdmin.java @@ -0,0 +1,121 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.admin; + +import org.apache.eventmesh.api.admin.Admin; +import org.apache.eventmesh.api.admin.TopicProperties; +import org.apache.eventmesh.connector.standalone.broker.MessageQueue; +import org.apache.eventmesh.connector.standalone.broker.StandaloneBroker; +import org.apache.eventmesh.connector.standalone.broker.model.TopicMetadata; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + +import io.cloudevents.CloudEvent; + +public class StandaloneAdmin implements Admin { + private final AtomicBoolean isStarted; + + private final StandaloneBroker standaloneBroker; + + public StandaloneAdmin(Properties properties) { + this.standaloneBroker = StandaloneBroker.getInstance(); + this.isStarted = new AtomicBoolean(false); + } + + @Override + public boolean isStarted() { + return isStarted.get(); + } + + @Override + public boolean isClosed() { + return !isStarted.get(); + } + + @Override + public void start() { + isStarted.compareAndSet(false, true); + } + + @Override + public void shutdown() { + isStarted.compareAndSet(true, false); + } + + @Override + public void init(Properties keyValue) throws Exception { + } + + @Override + public List getTopic() throws Exception { + ConcurrentHashMap messageContainer = this.standaloneBroker.getMessageContainer(); + List topicList = new ArrayList<>(); + for (TopicMetadata topicMetadata : messageContainer.keySet()) { + MessageQueue messageQueue = messageContainer.get(topicMetadata); + topicList.add(new TopicProperties( + topicMetadata.getTopicName(), + messageQueue.getPutIndex() - messageQueue.getTakeIndex() + )); + } + topicList.sort(Comparator.comparing(t -> t.name)); + return topicList; + } + + @Override + public void createTopic(String topicName) { + standaloneBroker.createTopicIfAbsent(topicName); + } + + @Override + public void deleteTopic(String topicName) { + standaloneBroker.deleteTopicIfExist(topicName); + } + + @Override + public List getEvent(String topicName, int offset, int length) throws Exception { + if (!this.standaloneBroker.checkTopicExist(topicName)) { + throw new Exception("The topic name doesn't exist in the message queue"); + } + ConcurrentHashMap messageContainer = this.standaloneBroker.getMessageContainer(); + long topicOffset = messageContainer.get(new TopicMetadata(topicName)).getTakeIndex(); + + List messageList = new ArrayList<>(); + for (int index = 0; index < length; index++) { + long messageOffset = topicOffset + offset + index; + CloudEvent event = this.standaloneBroker.getMessage(topicName, messageOffset); + if (event == null) { + break; + } + messageList.add(event); + } + return messageList; + } + + @Override + public void publish(CloudEvent cloudEvent) throws Exception { + this.standaloneBroker.putMessage(cloudEvent.getSubject(), cloudEvent); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/admin/StandaloneAdminAdaptor.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/admin/StandaloneAdminAdaptor.java new file mode 100644 index 0000000000..f3dfdd4f8a --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/admin/StandaloneAdminAdaptor.java @@ -0,0 +1,86 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.admin; + +import org.apache.eventmesh.api.admin.Admin; +import org.apache.eventmesh.api.admin.TopicProperties; + +import java.util.List; +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +public class StandaloneAdminAdaptor implements Admin { + + private StandaloneAdmin admin; + + public StandaloneAdminAdaptor() { + } + + @Override + public boolean isStarted() { + return admin.isStarted(); + } + + @Override + public boolean isClosed() { + return admin.isClosed(); + } + + @Override + public void start() { + admin.start(); + } + + @Override + public void shutdown() { + admin.shutdown(); + } + + @Override + public void init(Properties keyValue) throws Exception { + admin = new StandaloneAdmin(keyValue); + } + + @Override + public List getTopic() throws Exception { + return admin.getTopic(); + } + + @Override + public void createTopic(String topicName) throws Exception { + admin.createTopic(topicName); + } + + @Override + public void deleteTopic(String topicName) throws Exception { + admin.deleteTopic(topicName); + } + + @Override + public List getEvent(String topicName, int offset, int length) throws Exception { + return admin.getEvent(topicName, offset, length); + } + + @Override + public void publish(CloudEvent cloudEvent) throws Exception { + admin.publish(cloudEvent); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/MessageQueue.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/MessageQueue.java new file mode 100644 index 0000000000..902da62fbf --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/MessageQueue.java @@ -0,0 +1,232 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.broker; + +import org.apache.eventmesh.connector.standalone.broker.model.MessageEntity; + +import java.util.List; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +import com.google.common.base.Preconditions; + +/** + * This is a block queue, can get entity by offset. + * The queue is a FIFO data structure. + */ +public class MessageQueue { + + public MessageEntity[] items; + + private int takeIndex; + + private int putIndex; + + private int count; + + private final ReentrantLock lock; + + private final Condition notEmpty; + + private final Condition notFull; + + + public MessageQueue() { + this(2 << 10); + } + + public MessageQueue(int capacity) { + if (capacity <= 0) { + throw new IllegalArgumentException("capacity is illegal"); + } + this.items = new MessageEntity[capacity]; + this.lock = new ReentrantLock(); + this.notEmpty = lock.newCondition(); + this.notFull = lock.newCondition(); + } + + /** + * Insert the message at the tail of this queue, waiting for space to become available if the queue is full + * + * @param messageEntity + */ + public void put(MessageEntity messageEntity) throws InterruptedException { + Preconditions.checkNotNull(messageEntity); + ReentrantLock lock = this.lock; + lock.lockInterruptibly(); + try { + while (count == items.length) { + notFull.await(); + } + enqueue(messageEntity); + } finally { + lock.unlock(); + } + } + + /** + * Get the first message at this queue, waiting for the message is available if the queue is empty, + * this method will not remove the message + * + * @return MessageEntity + * @throws InterruptedException + */ + public MessageEntity take() throws InterruptedException { + ReentrantLock lock = this.lock; + lock.lockInterruptibly(); + try { + while (count == 0) { + notEmpty.await(); + } + return dequeue(); + } finally { + lock.unlock(); + } + } + + /** + * Get the first message at this queue, if the queue is empty return null immediately + * + * @return MessageEntity + */ + public MessageEntity peek() { + ReentrantLock lock = this.lock; + lock.lock(); + try { + return itemAt(takeIndex); + } finally { + lock.unlock(); + } + } + + /** + * Get the head in this queue + * + * @return MessageEntity + */ + public MessageEntity getHead() { + return peek(); + } + + /** + * Get the tail in this queue + * + * @return MessageEntity + */ + public MessageEntity getTail() { + ReentrantLock lock = this.lock; + lock.lock(); + try { + if (count == 0) { + return null; + } + int tailIndex = putIndex - 1; + if (tailIndex < 0) { + tailIndex += items.length; + } + return itemAt(tailIndex); + } finally { + lock.unlock(); + } + } + + /** + * Get the message by offset, since the offset is increment, so we can get the first message in this queue + * and calculate the index of this offset + * + * @param offset + * @return MessageEntity + */ + public MessageEntity getByOffset(long offset) { + ReentrantLock lock = this.lock; + lock.lock(); + try { + MessageEntity head = getHead(); + if (head == null) { + return null; + } + if (head.getOffset() > offset) { + throw new RuntimeException(String.format("The message has been deleted, offset: %s", offset)); + } + MessageEntity tail = getTail(); + if (tail == null || tail.getOffset() < offset) { + return null; + } + int offsetDis = (int) (head.getOffset() - offset); + int offsetIndex = takeIndex - offsetDis; + if (offsetIndex < 0) { + offsetIndex += items.length; + } + return itemAt(offsetIndex); + } finally { + lock.unlock(); + } + } + + public void removeHead() { + ReentrantLock lock = this.lock; + lock.lock(); + try { + if (count == 0) { + return; + } + items[takeIndex++] = null; + if (takeIndex == items.length) { + takeIndex = 0; + } + notFull.signalAll(); + } finally { + lock.unlock(); + } + } + + public int getSize() { + return count; + } + + + private MessageEntity itemAt(int index) { + return items[index]; + } + + private void enqueue(MessageEntity messageEntity) { + items[putIndex++] = messageEntity; + if (putIndex == items.length) { + putIndex = 0; + } + count++; + notEmpty.signalAll(); + } + + private MessageEntity dequeue() { + MessageEntity item = items[takeIndex++]; + if (takeIndex == items.length) { + takeIndex = 0; + } + notFull.signalAll(); + return item; + } + + public int getTakeIndex() { + return takeIndex; + } + + public int getPutIndex() { + return putIndex; + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/StandaloneBroker.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/StandaloneBroker.java new file mode 100644 index 0000000000..677ac46dd3 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/StandaloneBroker.java @@ -0,0 +1,162 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.broker; + +import org.apache.eventmesh.connector.standalone.broker.model.MessageEntity; +import org.apache.eventmesh.connector.standalone.broker.model.TopicMetadata; +import org.apache.eventmesh.connector.standalone.broker.task.HistoryMessageClearTask; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +import io.cloudevents.CloudEvent; + +/** + * This broker used to store event, it just support standalone mode, you shouldn't use this module in production environment + */ +public class StandaloneBroker { + + private final ConcurrentHashMap messageContainer; + + // todo: move the offset manage to consumer + private final ConcurrentHashMap offsetMap; + + private StandaloneBroker() { + this.messageContainer = new ConcurrentHashMap<>(); + this.offsetMap = new ConcurrentHashMap<>(); + startHistoryMessageCleanTask(); + } + + public ConcurrentHashMap getMessageContainer() { + return this.messageContainer; + } + + public ConcurrentHashMap getOffsetMap() { + return this.offsetMap; + } + + public static StandaloneBroker getInstance() { + return StandaloneBrokerInstanceHolder.instance; + } + + /** + * put message + * + * @param topicName topic name + * @param message message + * @throws InterruptedException + */ + public MessageEntity putMessage(String topicName, CloudEvent message) throws InterruptedException { + Pair pair = createTopicIfAbsent(topicName); + AtomicLong topicOffset = pair.getRight(); + MessageQueue messageQueue = pair.getLeft(); + + MessageEntity messageEntity = new MessageEntity( + new TopicMetadata(topicName), message, topicOffset.getAndIncrement(), System.currentTimeMillis()); + messageQueue.put(messageEntity); + + return messageEntity; + } + + /** + * Get the message, if the queue is empty then await + * + * @param topicName + */ + public CloudEvent takeMessage(String topicName) throws InterruptedException { + TopicMetadata topicMetadata = new TopicMetadata(topicName); + return messageContainer.computeIfAbsent(topicMetadata, k -> new MessageQueue()).take().getMessage(); + } + + /** + * Get the message, if the queue is empty return null + * + * @param topicName + */ + public CloudEvent getMessage(String topicName) { + TopicMetadata topicMetadata = new TopicMetadata(topicName); + MessageEntity head = messageContainer.computeIfAbsent(topicMetadata, k -> new MessageQueue()).getHead(); + if (head == null) { + return null; + } + return head.getMessage(); + } + + /** + * Get the message by offset + * + * @param topicName topic name + * @param offset offset + * @return CloudEvent + */ + public CloudEvent getMessage(String topicName, long offset) { + TopicMetadata topicMetadata = new TopicMetadata(topicName); + MessageEntity messageEntity = messageContainer.computeIfAbsent(topicMetadata, k -> new MessageQueue()).getByOffset(offset); + if (messageEntity == null) { + return null; + } + return messageEntity.getMessage(); + } + + private void startHistoryMessageCleanTask() { + Thread thread = new Thread(new HistoryMessageClearTask(messageContainer)); + thread.setDaemon(true); + thread.setName("StandaloneBroker-HistoryMessageCleanTask"); + thread.start(); + } + + public boolean checkTopicExist(String topicName) { + return messageContainer.containsKey(new TopicMetadata(topicName)); + } + + /** + * if the topic does not exist, create the topic + * + * @param topicName topicName + * @return messageQueue and offset + */ + public Pair createTopicIfAbsent(String topicName) { + TopicMetadata topicMetadata = new TopicMetadata(topicName); + MessageQueue messageQueue = messageContainer.computeIfAbsent(topicMetadata, k -> new MessageQueue()); + AtomicLong offset = offsetMap.computeIfAbsent(topicMetadata, k -> new AtomicLong()); + return Pair.of(messageQueue, offset); + } + + /** + * if the topic exists, delete the topic + * + * @param topicName topicName + */ + public void deleteTopicIfExist(String topicName) { + TopicMetadata topicMetadata = new TopicMetadata(topicName); + messageContainer.remove(topicMetadata); + } + + public void updateOffset(TopicMetadata topicMetadata, long offset) { + offsetMap.computeIfPresent(topicMetadata, (k, v) -> { + v.set(offset); + return v; + }); + } + + private static class StandaloneBrokerInstanceHolder { + private static final StandaloneBroker instance = new StandaloneBroker(); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/model/MessageEntity.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/model/MessageEntity.java new file mode 100644 index 0000000000..0225874b7c --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/model/MessageEntity.java @@ -0,0 +1,72 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.broker.model; + +import java.io.Serializable; + +import io.cloudevents.CloudEvent; + +public class MessageEntity implements Serializable { + + private TopicMetadata topicMetadata; + + private CloudEvent message; + + private long offset; + + private long createTimeMills; + + public MessageEntity(TopicMetadata topicMetadata, CloudEvent message, long offset, long currentTimeMills) { + this.topicMetadata = topicMetadata; + this.message = message; + this.offset = offset; + this.createTimeMills = currentTimeMills; + } + + public TopicMetadata getTopicMetadata() { + return topicMetadata; + } + + public void setTopicMetadata(TopicMetadata topicMetadata) { + this.topicMetadata = topicMetadata; + } + + public CloudEvent getMessage() { + return message; + } + + public void setMessage(CloudEvent message) { + this.message = message; + } + + public long getOffset() { + return offset; + } + + public void setOffset(long offset) { + this.offset = offset; + } + + public long getCreateTimeMills() { + return createTimeMills; + } + + public void setCreateTimeMills(long createTimeMills) { + this.createTimeMills = createTimeMills; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/model/TopicMetadata.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/model/TopicMetadata.java new file mode 100644 index 0000000000..bf4a249a01 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/model/TopicMetadata.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.broker.model; + +import java.io.Serializable; +import java.util.Objects; + +/** + * Topic metadata, each topic has it's own metadata + */ +public class TopicMetadata implements Serializable { + + private String topicName; + + public TopicMetadata(String topicName) { + this.topicName = topicName; + } + + public String getTopicName() { + return this.topicName; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof TopicMetadata)) { + return false; + } + TopicMetadata that = (TopicMetadata) o; + return Objects.equals(topicName, that.topicName); + } + + @Override + public int hashCode() { + return Objects.hash(topicName); + } + + @Override + public String toString() { + return "TopicMetadata{" + + + "topic='" + topicName + '\'' + + + '}'; + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/task/HistoryMessageClearTask.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/task/HistoryMessageClearTask.java new file mode 100644 index 0000000000..5499f331f2 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/task/HistoryMessageClearTask.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.broker.task; + +import org.apache.eventmesh.connector.standalone.broker.MessageQueue; +import org.apache.eventmesh.connector.standalone.broker.model.MessageEntity; +import org.apache.eventmesh.connector.standalone.broker.model.TopicMetadata; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This task used to clear the history message, the element in message queue can only be cleaned by this task. + */ +public class HistoryMessageClearTask implements Runnable { + + + private final Logger logger = LoggerFactory.getLogger(HistoryMessageClearTask.class); + + private final ConcurrentHashMap messageContainer; + + /** + * If the currentTimeMills - messageCreateTimeMills >= MESSAGE_STORE_WINDOW, then the message will be clear + */ + private static final long MESSAGE_STORE_WINDOW = 60 * 60 * 1000; + + public HistoryMessageClearTask(ConcurrentHashMap messageContainer) { + this.messageContainer = messageContainer; + } + + @Override + public void run() { + while (true) { + messageContainer.forEach((topicMetadata, messageQueue) -> { + long currentTimeMillis = System.currentTimeMillis(); + MessageEntity oldestMessage = messageQueue.getHead(); + if (oldestMessage == null) { + return; + } + if (currentTimeMillis - oldestMessage.getCreateTimeMills() >= MESSAGE_STORE_WINDOW) { + messageQueue.removeHead(); + } + }); + try { + Thread.sleep(TimeUnit.SECONDS.toMillis(1)); + } catch (InterruptedException e) { + logger.error("Thread is interrupted, thread name: {}", Thread.currentThread().getName(), e); + Thread.currentThread().interrupt(); + } + } + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/task/SubScribeTask.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/task/SubScribeTask.java new file mode 100644 index 0000000000..aec2adda99 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/broker/task/SubScribeTask.java @@ -0,0 +1,117 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.broker.task; + +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.EventMeshAction; +import org.apache.eventmesh.api.EventMeshAsyncConsumeContext; +import org.apache.eventmesh.connector.standalone.broker.StandaloneBroker; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; + +public class SubScribeTask implements Runnable { + + private String topicName; + private StandaloneBroker standaloneBroker; + private EventListener listener; + private volatile boolean isRunning; + + private AtomicInteger offset; + + private final Logger logger = LoggerFactory.getLogger(SubScribeTask.class); + + public SubScribeTask(String topicName, + StandaloneBroker standaloneBroker, + EventListener listener) { + this.topicName = topicName; + this.standaloneBroker = standaloneBroker; + this.listener = listener; + this.isRunning = true; + } + + @Override + public void run() { + while (isRunning) { + try { + logger.debug("execute subscribe task, topic: {}, offset: {}", topicName, offset); + if (offset == null) { + CloudEvent message = standaloneBroker.getMessage(topicName); + if (message != null) { + Object tmpOffset = message.getExtension("offset"); + if (tmpOffset instanceof Integer) { + offset = new AtomicInteger(Integer.parseInt(tmpOffset.toString())); + } else { + offset = new AtomicInteger(0); + } + + } + } + if (offset != null) { + CloudEvent message = standaloneBroker.getMessage(topicName, offset.get()); + if (message != null) { + EventMeshAsyncConsumeContext consumeContext = new EventMeshAsyncConsumeContext() { + @Override + public void commit(EventMeshAction action) { + switch (action) { + case CommitMessage: + // update offset + logger.info("message commit, topic: {}, current offset:{}", topicName, + offset.get()); + break; + case ReconsumeLater: + // don't update offset + break; + case ManualAck: + // update offset + offset.incrementAndGet(); + logger + .info("message ack, topic: {}, current offset:{}", topicName, offset.get()); + break; + default: + + } + } + }; + listener.consume(message, consumeContext); + } + } + + } catch (Exception ex) { + logger.error("consumer error, topic: {}, offset: {}", topicName, offset == null ? null : offset.get(), + ex); + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + logger.error("Thread is interrupted, topic: {}, offset: {} thread name: {}", + topicName, offset == null ? null : offset.get(), Thread.currentThread().getName(), e); + Thread.currentThread().interrupt(); + } + } + } + + public void shutdown() { + isRunning = false; + } + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/consumer/StandaloneConsumer.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/consumer/StandaloneConsumer.java new file mode 100644 index 0000000000..d6d24ffdf9 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/consumer/StandaloneConsumer.java @@ -0,0 +1,125 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.consumer; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.consumer.Consumer; +import org.apache.eventmesh.common.ThreadPoolFactory; +import org.apache.eventmesh.connector.standalone.broker.StandaloneBroker; +import org.apache.eventmesh.connector.standalone.broker.model.TopicMetadata; +import org.apache.eventmesh.connector.standalone.broker.task.SubScribeTask; + +import java.util.List; +import java.util.Objects; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicBoolean; + +import io.cloudevents.CloudEvent; + +public class StandaloneConsumer implements Consumer { + + private final StandaloneBroker standaloneBroker; + + private EventListener listener; + + private final AtomicBoolean isStarted; + + private final ConcurrentHashMap subscribeTaskTable; + + private final ExecutorService consumeExecutorService; + + public StandaloneConsumer(Properties properties) { + this.standaloneBroker = StandaloneBroker.getInstance(); + this.subscribeTaskTable = new ConcurrentHashMap<>(16); + this.isStarted = new AtomicBoolean(false); + this.consumeExecutorService = ThreadPoolFactory.createThreadPoolExecutor( + Runtime.getRuntime().availableProcessors() * 2, + Runtime.getRuntime().availableProcessors() * 2, + "StandaloneConsumerThread" + ); + } + + @Override + public boolean isStarted() { + return isStarted.get(); + } + + @Override + public boolean isClosed() { + return !isStarted.get(); + } + + @Override + public void start() { + isStarted.compareAndSet(false, true); + } + + @Override + public void shutdown() { + isStarted.compareAndSet(true, false); + subscribeTaskTable.forEach(((topic, subScribeTask) -> subScribeTask.shutdown())); + subscribeTaskTable.clear(); + } + + @Override + public void init(Properties keyValue) throws Exception { + + } + + @Override + public void updateOffset(List cloudEvents, AbstractContext context) { + cloudEvents.forEach(cloudEvent -> standaloneBroker.updateOffset( + new TopicMetadata(cloudEvent.getSubject()), Objects.requireNonNull((Long) cloudEvent.getExtension("offset"))) + ); + + } + + @Override + public void subscribe(String topic) throws Exception { + + if (subscribeTaskTable.containsKey(topic)) { + return; + } + synchronized (subscribeTaskTable) { + standaloneBroker.createTopicIfAbsent(topic); + SubScribeTask subScribeTask = new SubScribeTask(topic, standaloneBroker, listener); + subscribeTaskTable.put(topic, subScribeTask); + consumeExecutorService.execute(subScribeTask); + } + } + + @Override + public void unsubscribe(String topic) { + if (!subscribeTaskTable.containsKey(topic)) { + return; + } + synchronized (subscribeTaskTable) { + SubScribeTask subScribeTask = subscribeTaskTable.get(topic); + subScribeTask.shutdown(); + subscribeTaskTable.remove(topic); + } + } + + @Override + public void registerEventListener(EventListener listener) { + this.listener = listener; + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/consumer/StandaloneConsumerAdaptor.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/consumer/StandaloneConsumerAdaptor.java new file mode 100644 index 0000000000..79c5aadd5e --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/consumer/StandaloneConsumerAdaptor.java @@ -0,0 +1,83 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.consumer; + +import org.apache.eventmesh.api.AbstractContext; +import org.apache.eventmesh.api.EventListener; +import org.apache.eventmesh.api.consumer.Consumer; + +import java.util.List; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; + +public class StandaloneConsumerAdaptor implements Consumer { + + private StandaloneConsumer consumer; + + public StandaloneConsumerAdaptor() { + } + + @Override + public boolean isStarted() { + return consumer.isStarted(); + } + + @Override + public boolean isClosed() { + return consumer.isClosed(); + } + + @Override + public void start() { + consumer.start(); + } + + @Override + public void shutdown() { + consumer.shutdown(); + } + + @Override + public void init(Properties keyValue) throws Exception { + consumer = new StandaloneConsumer(keyValue); + } + + @Override + public void updateOffset(List cloudEvents, AbstractContext context) { + consumer.updateOffset(cloudEvents, context); + } + + @Override + public void subscribe(String topic) throws Exception { + consumer.subscribe(topic); + } + + @Override + public void unsubscribe(String topic) { + consumer.unsubscribe(topic); + } + + @Override + public void registerEventListener(EventListener listener) { + consumer.registerEventListener(listener); + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/producer/StandaloneProducer.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/producer/StandaloneProducer.java new file mode 100644 index 0000000000..4998338a67 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/producer/StandaloneProducer.java @@ -0,0 +1,142 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.producer; + +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.SendResult; +import org.apache.eventmesh.api.exception.ConnectorRuntimeException; +import org.apache.eventmesh.api.exception.OnExceptionContext; +import org.apache.eventmesh.connector.standalone.broker.StandaloneBroker; +import org.apache.eventmesh.connector.standalone.broker.model.MessageEntity; + +import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; + +import com.google.common.base.Preconditions; + +public class StandaloneProducer { + + private Logger logger = LoggerFactory.getLogger(StandaloneProducer.class); + + private StandaloneBroker standaloneBroker; + + private AtomicBoolean isStarted; + + public StandaloneProducer(Properties properties) { + this.standaloneBroker = StandaloneBroker.getInstance(); + this.isStarted = new AtomicBoolean(false); + } + + public boolean isStarted() { + return isStarted.get(); + } + + public boolean isClosed() { + return !isStarted.get(); + } + + public void start() { + isStarted.compareAndSet(false, true); + } + + public void shutdown() { + isStarted.compareAndSet(true, false); + } + + public StandaloneProducer init(Properties properties) throws Exception { + return new StandaloneProducer(properties); + } + + public SendResult publish(CloudEvent cloudEvent) { + Preconditions.checkNotNull(cloudEvent); + try { + MessageEntity messageEntity = standaloneBroker.putMessage(cloudEvent.getSubject(), cloudEvent); + SendResult sendResult = new SendResult(); + sendResult.setTopic(cloudEvent.getSubject()); + sendResult.setMessageId(String.valueOf(messageEntity.getOffset())); + return sendResult; + } catch (Exception e) { + logger.error("send message error, topic: {}", cloudEvent.getSubject(), e); + throw new ConnectorRuntimeException( + String.format("Send message error, topic: %s", cloudEvent.getSubject())); + } + } + + public void publish(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + Preconditions.checkNotNull(cloudEvent); + Preconditions.checkNotNull(sendCallback); + + try { + SendResult sendResult = publish(cloudEvent); + sendCallback.onSuccess(sendResult); + } catch (Exception ex) { + OnExceptionContext onExceptionContext = OnExceptionContext.builder() + .messageId(cloudEvent.getId()) + .topic(cloudEvent.getSubject()) + .exception(new ConnectorRuntimeException(ex)) + .build(); + sendCallback.onException(onExceptionContext); + } + } + + public void sendOneway(CloudEvent cloudEvent) { + publish(cloudEvent); + } + + public void sendAsync(CloudEvent cloudEvent, SendCallback sendCallback) { + Preconditions.checkNotNull(cloudEvent, "CloudEvent cannot be null"); + Preconditions.checkNotNull(sendCallback, "Callback cannot be null"); + // todo: current is not async + try { + SendResult sendResult = publish(cloudEvent); + sendCallback.onSuccess(sendResult); + } catch (Exception ex) { + OnExceptionContext onExceptionContext = OnExceptionContext.builder() + .messageId(cloudEvent.getId()) + .topic(cloudEvent.getSubject()) + .exception(new ConnectorRuntimeException(ex)) + .build(); + sendCallback.onException(onExceptionContext); + } + } + + public void request(CloudEvent cloudEvent, RequestReplyCallback rrCallback, long timeout) throws Exception { + throw new ConnectorRuntimeException("Request is not supported"); + } + + public boolean reply(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + throw new ConnectorRuntimeException("Reply is not supported"); + } + + public void checkTopicExist(String topic) throws Exception { + boolean exist = standaloneBroker.checkTopicExist(topic); + if (!exist) { + throw new ConnectorRuntimeException(String.format("topic:%s is not exist", topic)); + } + } + + public void setExtFields() { + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/producer/StandaloneProducerAdaptor.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/producer/StandaloneProducerAdaptor.java new file mode 100644 index 0000000000..d85161a54a --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/producer/StandaloneProducerAdaptor.java @@ -0,0 +1,90 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.producer; + +import org.apache.eventmesh.api.RequestReplyCallback; +import org.apache.eventmesh.api.SendCallback; +import org.apache.eventmesh.api.producer.Producer; + +import java.util.Properties; + +import io.cloudevents.CloudEvent; + +public class StandaloneProducerAdaptor implements Producer { + + private StandaloneProducer standaloneProducer; + + public StandaloneProducerAdaptor() { + } + + @Override + public boolean isStarted() { + return standaloneProducer.isStarted(); + } + + @Override + public boolean isClosed() { + return standaloneProducer.isClosed(); + } + + @Override + public void start() { + standaloneProducer.start(); + } + + @Override + public void shutdown() { + standaloneProducer.shutdown(); + } + + @Override + public void init(Properties properties) throws Exception { + standaloneProducer = new StandaloneProducer(properties); + } + + @Override + public void publish(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + standaloneProducer.publish(cloudEvent, sendCallback); + } + + @Override + public void sendOneway(CloudEvent cloudEvent) { + standaloneProducer.sendOneway(cloudEvent); + } + + @Override + public void request(CloudEvent cloudEvent, RequestReplyCallback rrCallback, long timeout) throws Exception { + standaloneProducer.request(cloudEvent, rrCallback, timeout); + } + + @Override + public boolean reply(CloudEvent cloudEvent, SendCallback sendCallback) throws Exception { + return standaloneProducer.reply(cloudEvent, sendCallback); + } + + @Override + public void checkTopicExist(String topic) throws Exception { + standaloneProducer.checkTopicExist(topic); + } + + @Override + public void setExtFields() { + standaloneProducer.setExtFields(); + } + +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/resource/StandaloneConnectorResourceService.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/resource/StandaloneConnectorResourceService.java new file mode 100644 index 0000000000..877d12f3ba --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/java/org/apache/eventmesh/connector/standalone/resource/StandaloneConnectorResourceService.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.resource; + +import org.apache.eventmesh.api.connector.ConnectorResourceService; + +public class StandaloneConnectorResourceService implements ConnectorResourceService { + + @Override + public void init() throws Exception { + + } + + @Override + public void release() throws Exception { + + } +} diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.admin.Admin b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.admin.Admin new file mode 100644 index 0000000000..2cfd20933a --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.admin.Admin @@ -0,0 +1,16 @@ +# 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. + +standalone=org.apache.eventmesh.connector.standalone.admin.StandaloneAdminAdaptor diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService new file mode 100644 index 0000000000..7b8e948112 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.connector.ConnectorResourceService @@ -0,0 +1,16 @@ +# 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. + +standalone=org.apache.eventmesh.connector.standalone.resource.StandaloneConnectorResourceService \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer new file mode 100644 index 0000000000..5ceb0eda96 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.consumer.Consumer @@ -0,0 +1,16 @@ +# 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. + +standalone=org.apache.eventmesh.connector.standalone.consumer.StandaloneConsumerAdaptor \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer new file mode 100644 index 0000000000..1b30d9837b --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/main/resources/META-INF/eventmesh/org.apache.eventmesh.api.producer.Producer @@ -0,0 +1,16 @@ +# 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. + +standalone=org.apache.eventmesh.connector.standalone.producer.StandaloneProducerAdaptor \ No newline at end of file diff --git a/eventmesh-connector-plugin/eventmesh-connector-standalone/src/test/java/org/apache/eventmesh/connector/standalone/broker/StandaloneBrokerTest.java b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/test/java/org/apache/eventmesh/connector/standalone/broker/StandaloneBrokerTest.java new file mode 100644 index 0000000000..651b18d749 --- /dev/null +++ b/eventmesh-connector-plugin/eventmesh-connector-standalone/src/test/java/org/apache/eventmesh/connector/standalone/broker/StandaloneBrokerTest.java @@ -0,0 +1,73 @@ +/* + * 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. + */ + +package org.apache.eventmesh.connector.standalone.broker; + +import org.apache.eventmesh.connector.standalone.broker.model.MessageEntity; + +import java.net.URI; + +import org.junit.Assert; +import org.junit.Test; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; + +public class StandaloneBrokerTest { + + @Test + public void getInstance() { + Assert.assertNotNull(StandaloneBroker.getInstance()); + } + + @Test + public void putMessage() throws InterruptedException { + StandaloneBroker instance = StandaloneBroker.getInstance(); + CloudEvent cloudEvent = CloudEventBuilder.v1() + .withId("test") + .withSource(URI.create("testsource")) + .withType("testType") + .build(); + MessageEntity messageEntity = instance.putMessage("test-topic", cloudEvent); + Assert.assertNotNull(messageEntity); + } + + @Test + public void takeMessage() throws InterruptedException { + StandaloneBroker instance = StandaloneBroker.getInstance(); + CloudEvent cloudEvent = CloudEventBuilder.v1() + .withId("test") + .withSource(URI.create("testsource")) + .withType("testType") + .build(); + instance.putMessage("test-topic", cloudEvent); + CloudEvent message = instance.takeMessage("test-topic"); + Assert.assertNotNull(message); + } + + @Test + public void getMessage() { + } + + @Test + public void testGetMessage() { + } + + @Test + public void checkTopicExist() { + } +} \ No newline at end of file diff --git a/eventmesh-connector-plugin/gradle.properties b/eventmesh-connector-plugin/gradle.properties new file mode 100644 index 0000000000..a9fd83fea0 --- /dev/null +++ b/eventmesh-connector-plugin/gradle.properties @@ -0,0 +1,16 @@ +# +# 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. +# \ No newline at end of file diff --git a/eventmesh-dashboard/.eslintrc.js b/eventmesh-dashboard/.eslintrc.js new file mode 100644 index 0000000000..120b007375 --- /dev/null +++ b/eventmesh-dashboard/.eslintrc.js @@ -0,0 +1,53 @@ +/* + * 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. + */ + +module.exports = { + env: { + browser: true, + es2021: true, + }, + extends: [ + 'plugin:react/recommended', + 'airbnb', + 'airbnb-typescript', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 13, + sourceType: 'module', + project: 'tsconfig.json', + }, + plugins: [ + 'react', + '@typescript-eslint', + ], + rules: { + 'react/react-in-jsx-scope': 'off', + 'react/function-component-definition': [ + 'error', + { + namedComponents: 'arrow-function', + }, + ], + 'no-param-reassign': 'off' + }, +}; diff --git a/eventmesh-dashboard/.gitignore b/eventmesh-dashboard/.gitignore new file mode 100644 index 0000000000..8453b69998 --- /dev/null +++ b/eventmesh-dashboard/.gitignore @@ -0,0 +1,132 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt +dist +next-env.d.ts + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and *not* Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel + +# VS code settings +.vscode + +# Yarn lock +yarn.lock \ No newline at end of file diff --git a/eventmesh-dashboard/README.md b/eventmesh-dashboard/README.md new file mode 100644 index 0000000000..c87e0421d2 --- /dev/null +++ b/eventmesh-dashboard/README.md @@ -0,0 +1,34 @@ +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. + +[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. + +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/eventmesh-dashboard/components/client/GrpcClientTable.tsx b/eventmesh-dashboard/components/client/GrpcClientTable.tsx new file mode 100644 index 0000000000..1ffdfeaa6f --- /dev/null +++ b/eventmesh-dashboard/components/client/GrpcClientTable.tsx @@ -0,0 +1,217 @@ +/* + * 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. + */ + +import { + HStack, + Select, + Input, + Table, + Thead, + Tbody, + Tr, + Th, + Td, + TableContainer, + useToast, + Box, + Button, +} from '@chakra-ui/react'; +import axios from 'axios'; +import { useContext, useEffect, useState } from 'react'; +import { AppContext } from '../../context/context'; + +interface GrpcClient { + env: string, + subsystem: string, + url: string, + pid: number, + host: string, + port: number, + version: string, + idc: string, + group: string, + purpose: string, + protocol: string, +} + +interface GrpcClientProps { + url: string, + group: string, +} + +interface RemoveGrpcClientRequest { + url: string, +} + +const GrpcClientRow = ({ + url, group, +}: GrpcClientProps) => { + const { state } = useContext(AppContext); + + const toast = useToast(); + const [loading, setLoading] = useState(false); + const onRemoveClick = async () => { + try { + setLoading(true); + await axios.delete(`${state.endpoint}/client/grpc`, { + data: { + url, + }, + }); + setLoading(false); + } catch (error) { + if (axios.isAxiosError(error)) { + toast({ + title: 'Failed to remove the gRPC Client', + description: error.message, + status: 'error', + duration: 3000, + isClosable: true, + }); + } + } + }; + + return ( + + {url} + {group} + + + + + + + ); +}; + +const GrpcClientTable = () => { + const { state } = useContext(AppContext); + + const [searchInput, setSearchInput] = useState(''); + const handleSearchInputChange = (event: React.FormEvent) => { + setSearchInput(event.currentTarget.value); + }; + + const [groupSet, setGroupSet] = useState>(new Set()); + const [groupFilter, setGroupFilter] = useState(''); + const handleGroupSelectChange = (event: React.FormEvent) => { + setGroupFilter(event.currentTarget.value); + }; + + const [GrpcClientList, setGrpcClientList] = useState([]); + const toast = useToast(); + useEffect(() => { + const fetch = async () => { + try { + const { data } = await axios.get(`${state.endpoint}/client/grpc`); + setGrpcClientList(data); + + const nextGroupSet = new Set(); + data.forEach(({ group }) => { + nextGroupSet.add(group); + }); + setGroupSet(nextGroupSet); + } catch (error) { + if (axios.isAxiosError(error)) { + toast({ + title: 'Failed to fetch the list of gRPC Clients', + description: 'Unable to connect to the EventMesh daemon', + status: 'error', + duration: 3000, + isClosable: true, + }); + setGrpcClientList([]); + } + } + }; + + fetch(); + }, []); + + return ( + + + + + + + + + + + + + + + + + {GrpcClientList && GrpcClientList.filter(({ + url, group, + }) => { + if (searchInput && !url.includes(searchInput)) { + return false; + } + if (groupFilter && groupFilter !== group) { + return false; + } + return true; + }).map(({ + url, group, + }) => ( + + ))} + +
URLGroupAction
+
+
+ ); +}; + +export default GrpcClientTable; diff --git a/eventmesh-dashboard/components/client/HTTPClientTable.tsx b/eventmesh-dashboard/components/client/HTTPClientTable.tsx new file mode 100644 index 0000000000..832ea91bdc --- /dev/null +++ b/eventmesh-dashboard/components/client/HTTPClientTable.tsx @@ -0,0 +1,217 @@ +/* + * 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. + */ + +import { + HStack, + Select, + Input, + Table, + Thead, + Tbody, + Tr, + Th, + Td, + TableContainer, + useToast, + Box, + Button, +} from '@chakra-ui/react'; +import axios from 'axios'; +import { useContext, useEffect, useState } from 'react'; +import { AppContext } from '../../context/context'; + +interface HTTPClient { + env: string, + subsystem: string, + url: string, + pid: number, + host: string, + port: number, + version: string, + idc: string, + group: string, + purpose: string, + protocol: string, +} + +interface HTTPClientProps { + url: string, + group: string, +} + +interface RemoveHTTPClientRequest { + url: string, +} + +const HTTPClientRow = ({ + url, group, +}: HTTPClientProps) => { + const { state } = useContext(AppContext); + + const toast = useToast(); + const [loading, setLoading] = useState(false); + const onRemoveClick = async () => { + try { + setLoading(true); + await axios.delete(`${state.endpoint}/client/http`, { + data: { + url, + }, + }); + setLoading(false); + } catch (error) { + if (axios.isAxiosError(error)) { + toast({ + title: 'Failed to remove the HTTP Client', + description: error.message, + status: 'error', + duration: 3000, + isClosable: true, + }); + } + } + }; + + return ( + + {url} + {group} + + + + + + + ); +}; + +const HTTPClientTable = () => { + const { state } = useContext(AppContext); + + const [searchInput, setSearchInput] = useState(''); + const handleSearchInputChange = (event: React.FormEvent) => { + setSearchInput(event.currentTarget.value); + }; + + const [groupSet, setGroupSet] = useState>(new Set()); + const [groupFilter, setGroupFilter] = useState(''); + const handleGroupSelectChange = (event: React.FormEvent) => { + setGroupFilter(event.currentTarget.value); + }; + + const [HTTPClientList, setHTTPClientList] = useState([]); + const toast = useToast(); + useEffect(() => { + const fetch = async () => { + try { + const { data } = await axios.get(`${state.endpoint}/client/http`); + setHTTPClientList(data); + + const nextGroupSet = new Set(); + data.forEach(({ group }) => { + nextGroupSet.add(group); + }); + setGroupSet(nextGroupSet); + } catch (error) { + if (axios.isAxiosError(error)) { + toast({ + title: 'Failed to fetch the list of HTTP Clients', + description: 'Unable to connect to the EventMesh daemon', + status: 'error', + duration: 3000, + isClosable: true, + }); + setHTTPClientList([]); + } + } + }; + + fetch(); + }, []); + + return ( + + + + + + + + + + + + + + + + + {HTTPClientList && HTTPClientList.filter(({ + url, group, + }) => { + if (searchInput && !url.includes(searchInput)) { + return false; + } + if (groupFilter && groupFilter !== group) { + return false; + } + return true; + }).map(({ + url, group, + }) => ( + + ))} + +
URLGroupAction
+
+
+ ); +}; + +export default HTTPClientTable; diff --git a/eventmesh-dashboard/components/client/TCPClientTable.tsx b/eventmesh-dashboard/components/client/TCPClientTable.tsx new file mode 100644 index 0000000000..dc2458901d --- /dev/null +++ b/eventmesh-dashboard/components/client/TCPClientTable.tsx @@ -0,0 +1,223 @@ +/* + * 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. + */ + +import { + HStack, + Select, + Input, + Table, + Thead, + Tbody, + Tr, + Th, + Td, + TableContainer, + useToast, + Box, + Button, +} from '@chakra-ui/react'; +import axios from 'axios'; +import { useContext, useEffect, useState } from 'react'; +import { AppContext } from '../../context/context'; + +interface TCPClient { + env: string, + subsystem: string, + url: string, + pid: number, + host: string, + port: number, + version: string, + idc: string, + group: string, + purpose: string, + protocol: string, +} + +interface TCPClientProps { + host: string, + port: number, + group: string, +} + +interface RemoveTCPClientRequest { + host: string, + port: number, +} + +const TCPClientRow = ({ + host, port, group, +}: TCPClientProps) => { + const { state } = useContext(AppContext); + + const toast = useToast(); + const [loading, setLoading] = useState(false); + const onRemoveClick = async () => { + try { + setLoading(true); + await axios.delete(`${state.endpoint}/client/tcp`, { + data: { + host, + port, + }, + }); + setLoading(false); + } catch (error) { + if (axios.isAxiosError(error)) { + toast({ + title: 'Failed to remove the TCP Client', + description: error.message, + status: 'error', + duration: 3000, + isClosable: true, + }); + } + } + }; + + return ( + + {`${host}:${port}`} + {group} + + + + + + + ); +}; + +const TCPClientTable = () => { + const { state } = useContext(AppContext); + + const [searchInput, setSearchInput] = useState(''); + const handleSearchInputChange = (event: React.FormEvent) => { + setSearchInput(event.currentTarget.value); + }; + + const [groupSet, setGroupSet] = useState>(new Set()); + const [groupFilter, setGroupFilter] = useState(''); + const handleGroupSelectChange = (event: React.FormEvent) => { + setGroupFilter(event.currentTarget.value); + }; + + const [TCPClientList, setTCPClientList] = useState([]); + const toast = useToast(); + useEffect(() => { + const fetch = async () => { + try { + const { data } = await axios.get(`${state.endpoint}/client/tcp`); + setTCPClientList(data); + + const nextGroupSet = new Set(); + data.forEach(({ group }) => { + nextGroupSet.add(group); + }); + setGroupSet(nextGroupSet); + } catch (error) { + if (axios.isAxiosError(error)) { + toast({ + title: 'Failed to fetch the list of TCP Clients', + description: 'Unable to connect to the EventMesh daemon', + status: 'error', + duration: 3000, + isClosable: true, + }); + setTCPClientList([]); + } + } + }; + + fetch(); + }, []); + + return ( + + + + + + + + + + + + + + + + + + {TCPClientList && TCPClientList.filter(({ + host, port, group, + }) => { + const address = `${host}:${port}`; + if (searchInput && !address.includes(searchInput)) { + return false; + } + if (groupFilter && groupFilter !== group) { + return false; + } + return true; + }).map(({ + host, port, group, + }) => ( + + ))} + +
HostHostGroupAction
+
+
+ ); +}; + +export default TCPClientTable; diff --git a/eventmesh-dashboard/components/event/EventTable.tsx b/eventmesh-dashboard/components/event/EventTable.tsx new file mode 100644 index 0000000000..b0d0a13df9 --- /dev/null +++ b/eventmesh-dashboard/components/event/EventTable.tsx @@ -0,0 +1,371 @@ +/* + * 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. + */ + +import { + HStack, + Input, + Table, + Thead, + Tbody, + Tr, + Th, + Td, + TableContainer, + useToast, + Box, + Button, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + useDisclosure, + Select, + VStack, + Textarea, +} from '@chakra-ui/react'; +import axios from 'axios'; +import { useContext, useEffect, useState } from 'react'; +import { CloudEvent } from 'cloudevents'; +import { AppContext } from '../../context/context'; + +interface Topic { + name: string, + messageCount: number, +} + +interface EventProps { + event: CloudEvent, +} + +interface CreateEventRequest { + event: CloudEvent, +} + +const CreateEventModal = () => { + const { state } = useContext(AppContext); + + const { isOpen, onOpen, onClose } = useDisclosure(); + + const [id, setId] = useState(''); + const handleIdChange = (event: React.FormEvent) => { + setId(event.currentTarget.value); + }; + + const [source, setSource] = useState(''); + const handleSourceChange = (event: React.FormEvent) => { + setSource(event.currentTarget.value); + }; + + const [subject, setSubject] = useState(''); + const handleSubjectChange = (event: React.FormEvent) => { + setSubject(event.currentTarget.value); + }; + + const [type, setType] = useState(''); + const handleTypeChange = (event: React.FormEvent) => { + setType(event.currentTarget.value); + }; + + const [data, setData] = useState(''); + const handleDataChange = (event: React.FormEvent) => { + setData(event.currentTarget.value); + }; + + const toast = useToast(); + const [loading, setLoading] = useState(false); + const onCreateClick = async () => { + try { + setLoading(true); + await axios.post(`${state.endpoint}/event`, new CloudEvent({ + source, + subject, + type, + data, + specversion: '1.0', + })); + onClose(); + } catch (error) { + if (axios.isAxiosError(error)) { + toast({ + title: 'Failed to publish the event', + description: error.message, + status: 'error', + duration: 3000, + isClosable: true, + }); + } + } finally { + setLoading(false); + } + }; + + return ( + <> + + + + + Create Event + + + + + + + + + + + + + + + + + + + ); +}; + +const EventRow = ({ + event, +}: EventProps) => { + const { isOpen, onOpen, onClose } = useDisclosure(); + const eventDataBase64 = event.data_base64 || ''; + const eventData = Buffer.from(eventDataBase64, 'base64').toString('utf-8'); + + return ( + <> + + + + Event Data + + + +