This is an automated email from the ASF dual-hosted git repository.

aaronai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-clients.git


The following commit(s) were added to refs/heads/master by this push:
     new e96712e8 Fix a series of issues (#533)
e96712e8 is described below

commit e96712e854ca81fe31b475d563e115f9b3b2e61e
Author: Yan Chao Mei <[email protected]>
AuthorDate: Fri Jun 2 22:14:48 2023 +0800

    Fix a series of issues (#533)
    
    * Using poetry as dependencies management & publishing tools
    
    * Rename rocketmq-client to rocketmq
    
    * Add publishing Steps
    
    * Add logging module support
    
    * Format code
    
    * fix style & license issues
    
    * add license for python client protocol
    
    ---------
    
    Co-authored-by: Aaron Ai <[email protected]>
    Co-authored-by: Aaron Ai <[email protected]>
---
 .github/workflows/python_build.yml                 |   4 +-
 .gitignore                                         |   3 +-
 python/README-CN.md                                |  33 +-
 python/README.md                                   |  32 +-
 python/client/rpc_client.py                        | 106 ------
 python/poetry.lock                                 | 331 +++++++++++++++++
 python/protocol/definition_pb2.py                  |  99 -----
 python/protocol/service_pb2.py                     | 110 ------
 python/pyproject.toml                              |  49 +++
 python/requirements.txt                            |   3 -
 .../__init__.py}                                   |  29 +-
 python/{protocol/__init__.py => rocketmq/foo.py}   |   8 +-
 .../message => rocketmq}/message_id_codec.py       |   0
 python/{ => rocketmq}/protocol/__init__.py         |   6 +-
 python/{ => rocketmq}/protocol/admin_pb2.py        |  26 +-
 python/rocketmq/protocol/admin_pb2.pyi             |  40 +++
 python/{ => rocketmq}/protocol/admin_pb2_grpc.py   |  18 +-
 python/rocketmq/protocol/definition_pb2.py         | 109 ++++++
 python/rocketmq/protocol/definition_pb2.pyi        | 398 +++++++++++++++++++++
 .../{ => rocketmq}/protocol/definition_pb2_grpc.py |   4 +-
 python/rocketmq/protocol/service_pb2.py            | 102 ++++++
 python/rocketmq/protocol/service_pb2.pyi           | 294 +++++++++++++++
 python/{ => rocketmq}/protocol/service_pb2_grpc.py | 138 +++----
 python/rocketmq/rpc_client.py                      | 117 ++++++
 python/{protocol => tests}/__init__.py             |   6 +-
 .../definition_pb2_grpc.py => tests/test_foo.py}   |  13 +-
 26 files changed, 1617 insertions(+), 461 deletions(-)

diff --git a/.github/workflows/python_build.yml 
b/.github/workflows/python_build.yml
index 2fd44c09..cbee5167 100644
--- a/.github/workflows/python_build.yml
+++ b/.github/workflows/python_build.yml
@@ -15,7 +15,7 @@ jobs:
       - run: python -m pip install flake8
       - name: flake8
         run: |
-          flake8 --ignore=E501,W503 --exclude python/protocol python
+          flake8 --ignore=E501,W503 --exclude python/rocketmq/protocol python
   isort:
     runs-on: ubuntu-latest
     steps:
@@ -28,7 +28,7 @@ jobs:
       - run: python -m pip install isort
       - name: isort
         run: |
-          isort --check --diff --skip python/protocol python
+          isort --check --diff --skip python/rocketmq/protocol python
   black:
     runs-on: ubuntu-latest
     steps:
diff --git a/.gitignore b/.gitignore
index c917b4bb..00a3ab08 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,4 +52,5 @@ golang/*.exe
 *.pyo
 *.pyd
 python/myvenv/
-python/__pycache__/
\ No newline at end of file
+python/__pycache__/
+python/dist
\ No newline at end of file
diff --git a/python/README-CN.md b/python/README-CN.md
index bc417119..3832808b 100644
--- a/python/README-CN.md
+++ b/python/README-CN.md
@@ -13,26 +13,31 @@
 
 ## 快速开始
 
-推荐使用 Python 虚拟环境进行开发,可以按照以下步骤操作:
-
-首先切换到当前仓库的 `python` 子目录,然后执行以下命令创建一个新的虚拟环境:
-
-```sh
-python3 -m venv myvenv
+我们使用 Poetry 作为依赖管理和发布的工具。你可以在 Poetry 
的[官方网站]((https://python-poetry.org/))了解到关于它的更多信息。这里是一些在开发阶段你会使用到的 Poetry 命令:
+
+```shell
+# 创建并激活 python3 的虚拟环境
+poetry env use python3
+# 自动安装工程相关的依赖
+poetry install
+# 进入虚拟环境中的 shell
+poetry shell
 ```
 
-其次开始激活虚拟环境。激活方法取决于具体的操作系统:
+我们使用 pytest 来作为当前项目的测试框架,你可以通过直接执行 `pytest` 命令来运行所有的测试。
 
-* 对于Windows,执行:`myvenv\Scripts\activate.bat`
-* 对于macOS/Linux:执行:`source myvenv/bin/activate`
+## 发布步骤
 
-执行以下命令以安装所需的依赖库:
+我们使用 PyPi 来帮助用户更好地在自己的工程中引入并使用客户端。为了将客户端发布到 PyPi,可以执行以下命令:
 
-```sh
-pip install -r requirements.txt
+```shell
+# 构建包
+poetry build
+# 将包发布到远程仓库
+poetry publish -u username -p password
 ```
 
 ## 目前进展
 
-* 协议层代码生成完毕
-* rpcClient完成部分
+* 协议层代码生成完毕。
+* `rpc_client.py` 完成部分。
diff --git a/python/README.md b/python/README.md
index 4bb60f8a..256548ee 100644
--- a/python/README.md
+++ b/python/README.md
@@ -13,27 +13,31 @@ Here are some preparations you may need to know (or refer 
to [here](https://rock
 
 ## Getting Started
 
-Clone the current repository to your local machine and set up a virtual 
environment for development, which will help you manage dependencies more 
efficiently. Follow the steps below:
-
-Navigate to the `python` subdirectory and execute the command below to create 
a new virtual environment:
-
-```sh
-python3 -m venv myvenv
+We are using Poetry as the dependency management & publishing tool. You can 
find out more details about Poetry from its 
[website](https://python-poetry.org/). Here is the related command of Poetry 
you may use for development.
+
+```shell
+# Create a virtual environment and activate it.
+poetry env use python3
+# Installs the project dependencies.
+poetry install
+# Spawns a shell within the virtual environment.
+poetry shell
 ```
 
-Activate the virtual environment. The activation method depends on your 
operating system:
+We use pytest as the testing framework for the current project, and you can 
execute `pytest` directly to run all tests.
 
-* For Windows, execute: `myvenv\Scripts\activate.bat`
-* For macOS/Linux: execute: `source myvenv/bin/activate`
+## Publishing Steps
 
-Install the required dependency libraries by executing the following command:
+We utilize PyPI to help users easily introduce and use the Python client in 
their projects. To publish a package to PyPI, please register an account in 
advance, then execute the following command.
 
-```sh
-pip install -r requirements.txt
+```shell
+# Builds a package, as a tarball and a wheel by default.
+poetry build
+# Publishes a package to a remote repository.
+poetry publish -u username -p password
 ```
 
 ## Current Progress
 
 * Protocol layer code generation is completed.
-
-* Partial completion of rpcClient.
+* Partial completion of `rpc_client.py`.
diff --git a/python/client/rpc_client.py b/python/client/rpc_client.py
deleted file mode 100644
index 1ed9b5e3..00000000
--- a/python/client/rpc_client.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 time
-from datetime import timedelta
-
-import protocol.service_pb2_grpc as service
-from grpc import aio, insecure_channel, ssl_channel_credentials
-
-
-class RpcClient:
-    CONNECT_TIMEOUT_MILLIS = 3 * 1000
-    GRPC_MAX_MESSAGE_SIZE = 2 * 31 - 1
-
-    def __init__(self, endpoints, ssl_enabled):
-        channel_options = [
-            ("grpc.max_send_message_length", -1),
-            ("grpc.max_receive_message_length", -1),
-            ("grpc.connect_timeout_ms", self.CONNECT_TIMEOUT_MILLIS),
-        ]
-        if ssl_enabled:
-            ssl_credentials = ssl_channel_credentials()
-            self.channel = aio.secure_channel(
-                endpoints.getGrpcTarget(), ssl_credentials, 
options=channel_options
-            )
-        else:
-            self.channel = insecure_channel(
-                endpoints.getGrpcTarget(), options=channel_options
-            )
-
-        self.activity_nano_time = time.monotonic_ns()
-
-    def __del__(self):
-        self.channel.close()
-
-    def idle_duration(self):
-        return timedelta(
-            microseconds=(time.monotonic_ns() - self.activity_nano_time) / 1000
-        )
-
-    async def query_route(self, request, timeout_seconds: int):
-        self.activity_nano_time = time.monotonic_ns()
-        stub = service.MessagingServiceStub(self.channel)
-        return await stub.QueryRoute(request, timeout=timeout_seconds)
-
-    async def heartbeat(self, request, timeout_seconds: int):
-        self.activity_nano_time = time.monotonic_ns()
-        stub = service.MessagingServiceStub(self.channel)
-        return await stub.Heartbeat(request, timeout=timeout_seconds)
-
-    async def send_message(self, request, timeout_seconds: int):
-        self.activity_nano_time = time.monotonic_ns()
-        stub = service.MessagingServiceStub(self.channel)
-        return await stub.SendMessage(request, timeout=timeout_seconds)
-
-    async def query_assignment(self, request, timeout_seconds: int):
-        self.activity_nano_time = time.monotonic_ns()
-        stub = service.MessagingServiceStub(self.channel)
-        return await stub.QueryAssignment(request, timeout=timeout_seconds)
-
-    # TODO: Not yet implemented
-    async def receive_message(self, metadata, request, timeout_seconds: int):
-        pass
-
-    async def ack_message(self, request, timeout_seconds: int):
-        self.activity_nano_time = time.monotonic_ns()
-        stub = service.MessagingServiceStub(self.channel)
-        return await stub.AckMessage(request, timeout=timeout_seconds)
-
-    async def change_invisible_duration(self, request, timeout_seconds: int):
-        self.activity_nano_time = time.monotonic_ns()
-        stub = service.MessagingServiceStub(self.channel)
-        return await stub.ChangeInvisibleDuration(request, 
timeout=timeout_seconds)
-
-    async def forward_message_to_dead_letter_queue(self, request, 
timeout_seconds: int):
-        self.activity_nano_time = time.monotonic_ns()
-        stub = service.MessagingServiceStub(self.channel)
-        return await stub.ForwardMessageToDeadLetterQueue(
-            request, timeout=timeout_seconds
-        )
-
-    async def end_transaction(self, request, timeout_seconds: int):
-        self.activity_nano_time = time.monotonic_ns()
-        stub = service.MessagingServiceStub(self.channel)
-        return await stub.EndTransaction(request, timeout=timeout_seconds)
-
-    async def notify_client_termination(self, request, timeout_seconds: int):
-        self.activity_nano_time = time.monotonic_ns()
-        stub = service.MessagingServiceStub(self.channel)
-        return await stub.NotifyClientTermination(request, 
timeout=timeout_seconds)
-
-    # TODO: Not yet implemented
-    async def telemetry(self, metadata, duration, response_observer):
-        pass
diff --git a/python/poetry.lock b/python/poetry.lock
new file mode 100644
index 00000000..14b1e262
--- /dev/null
+++ b/python/poetry.lock
@@ -0,0 +1,331 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file is automatically @generated by Poetry 1.5.1 and should not be 
changed by hand.
+
+[[package]]
+name = "certifi"
+version = "2023.5.7"
+description = "Python package for providing Mozilla's CA Bundle."
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "certifi-2023.5.7-py3-none-any.whl", hash = 
"sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"},
+    {file = "certifi-2023.5.7.tar.gz", hash = 
"sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = 
"!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+    {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = 
"sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+    {file = "colorama-0.4.6.tar.gz", hash = 
"sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.1.1"
+description = "Backport of PEP 654 (exception groups)"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = 
"sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"},
+    {file = "exceptiongroup-1.1.1.tar.gz", hash = 
"sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"},
+]
+
+[package.extras]
+test = ["pytest (>=6)"]
+
+[[package]]
+name = "grpcio"
+version = "1.54.2"
+description = "HTTP/2-based RPC framework"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "grpcio-1.54.2-cp310-cp310-linux_armv7l.whl", hash = 
"sha256:40e1cbf69d6741b40f750f3cccc64326f927ac6145a9914d33879e586002350c"},
+    {file = "grpcio-1.54.2-cp310-cp310-macosx_12_0_universal2.whl", hash = 
"sha256:2288d76e4d4aa7ef3fe7a73c1c470b66ea68e7969930e746a8cd8eca6ef2a2ea"},
+    {file = "grpcio-1.54.2-cp310-cp310-manylinux_2_17_aarch64.whl", hash = 
"sha256:c0e3155fc5335ec7b3b70f15230234e529ca3607b20a562b6c75fb1b1218874c"},
+    {file = 
"grpcio-1.54.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = 
"sha256:9bf88004fe086c786dc56ef8dd6cb49c026833fdd6f42cb853008bce3f907148"},
+    {file = 
"grpcio-1.54.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", 
hash = 
"sha256:2be88c081e33f20630ac3343d8ad9f1125f32987968e9c8c75c051c9800896e8"},
+    {file = "grpcio-1.54.2-cp310-cp310-musllinux_1_1_i686.whl", hash = 
"sha256:33d40954199bddbb6a78f8f6f2b2082660f381cd2583ec860a6c2fa7c8400c08"},
+    {file = "grpcio-1.54.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = 
"sha256:b52d00d1793d290c81ad6a27058f5224a7d5f527867e5b580742e1bd211afeee"},
+    {file = "grpcio-1.54.2-cp310-cp310-win32.whl", hash = 
"sha256:881d058c5ccbea7cc2c92085a11947b572498a27ef37d3eef4887f499054dca8"},
+    {file = "grpcio-1.54.2-cp310-cp310-win_amd64.whl", hash = 
"sha256:0212e2f7fdf7592e4b9d365087da30cb4d71e16a6f213120c89b4f8fb35a3ab3"},
+    {file = "grpcio-1.54.2-cp311-cp311-linux_armv7l.whl", hash = 
"sha256:1e623e0cf99a0ac114f091b3083a1848dbc64b0b99e181473b5a4a68d4f6f821"},
+    {file = "grpcio-1.54.2-cp311-cp311-macosx_10_10_universal2.whl", hash = 
"sha256:66233ccd2a9371158d96e05d082043d47dadb18cbb294dc5accfdafc2e6b02a7"},
+    {file = "grpcio-1.54.2-cp311-cp311-manylinux_2_17_aarch64.whl", hash = 
"sha256:4cb283f630624ebb16c834e5ac3d7880831b07cbe76cb08ab7a271eeaeb8943e"},
+    {file = 
"grpcio-1.54.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = 
"sha256:2a1e601ee31ef30a9e2c601d0867e236ac54c922d32ed9f727b70dd5d82600d5"},
+    {file = 
"grpcio-1.54.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", 
hash = 
"sha256:f8da84bbc61a4e92af54dc96344f328e5822d574f767e9b08e1602bb5ddc254a"},
+    {file = "grpcio-1.54.2-cp311-cp311-musllinux_1_1_i686.whl", hash = 
"sha256:5008964885e8d23313c8e5ea0d44433be9bfd7e24482574e8cc43c02c02fc796"},
+    {file = "grpcio-1.54.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = 
"sha256:a2f5a1f1080ccdc7cbaf1171b2cf384d852496fe81ddedeb882d42b85727f610"},
+    {file = "grpcio-1.54.2-cp311-cp311-win32.whl", hash = 
"sha256:b74ae837368cfffeb3f6b498688a123e6b960951be4dec0e869de77e7fa0439e"},
+    {file = "grpcio-1.54.2-cp311-cp311-win_amd64.whl", hash = 
"sha256:8cdbcbd687e576d48f7886157c95052825ca9948c0ed2afdc0134305067be88b"},
+    {file = "grpcio-1.54.2-cp37-cp37m-linux_armv7l.whl", hash = 
"sha256:782f4f8662a2157c4190d0f99eaaebc602899e84fb1e562a944e5025929e351c"},
+    {file = "grpcio-1.54.2-cp37-cp37m-macosx_10_10_universal2.whl", hash = 
"sha256:714242ad0afa63a2e6dabd522ae22e1d76e07060b5af2ddda5474ba4f14c2c94"},
+    {file = "grpcio-1.54.2-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = 
"sha256:f900ed4ad7a0f1f05d35f955e0943944d5a75f607a836958c6b8ab2a81730ef2"},
+    {file = 
"grpcio-1.54.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = 
"sha256:96a41817d2c763b1d0b32675abeb9179aa2371c72aefdf74b2d2b99a1b92417b"},
+    {file = 
"grpcio-1.54.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash 
= "sha256:70fcac7b94f4c904152809a050164650ac81c08e62c27aa9f156ac518029ebbe"},
+    {file = "grpcio-1.54.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = 
"sha256:fd6c6c29717724acf9fc1847c4515d57e4dc12762452457b9cb37461f30a81bb"},
+    {file = "grpcio-1.54.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = 
"sha256:c2392f5b5d84b71d853918687d806c1aa4308109e5ca158a16e16a6be71041eb"},
+    {file = "grpcio-1.54.2-cp37-cp37m-win_amd64.whl", hash = 
"sha256:51630c92591d6d3fe488a7c706bd30a61594d144bac7dee20c8e1ce78294f474"},
+    {file = "grpcio-1.54.2-cp38-cp38-linux_armv7l.whl", hash = 
"sha256:b04202453941a63b36876a7172b45366dc0cde10d5fd7855c0f4a4e673c0357a"},
+    {file = "grpcio-1.54.2-cp38-cp38-macosx_10_10_universal2.whl", hash = 
"sha256:89dde0ac72a858a44a2feb8e43dc68c0c66f7857a23f806e81e1b7cc7044c9cf"},
+    {file = "grpcio-1.54.2-cp38-cp38-manylinux_2_17_aarch64.whl", hash = 
"sha256:09d4bfd84686cd36fd11fd45a0732c7628308d094b14d28ea74a81db0bce2ed3"},
+    {file = 
"grpcio-1.54.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = 
"sha256:7fc2b4edb938c8faa4b3c3ea90ca0dd89b7565a049e8e4e11b77e60e4ed2cc05"},
+    {file = 
"grpcio-1.54.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash 
= "sha256:61f7203e2767800edee7a1e1040aaaf124a35ce0c7fe0883965c6b762defe598"},
+    {file = "grpcio-1.54.2-cp38-cp38-musllinux_1_1_i686.whl", hash = 
"sha256:e416c8baf925b5a1aff31f7f5aecc0060b25d50cce3a5a7255dc5cf2f1d4e5eb"},
+    {file = "grpcio-1.54.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = 
"sha256:dc80c9c6b608bf98066a038e0172013a49cfa9a08d53335aefefda2c64fc68f4"},
+    {file = "grpcio-1.54.2-cp38-cp38-win32.whl", hash = 
"sha256:8d6192c37a30a115f4663592861f50e130caed33efc4eec24d92ec881c92d771"},
+    {file = "grpcio-1.54.2-cp38-cp38-win_amd64.whl", hash = 
"sha256:46a057329938b08e5f0e12ea3d7aed3ecb20a0c34c4a324ef34e00cecdb88a12"},
+    {file = "grpcio-1.54.2-cp39-cp39-linux_armv7l.whl", hash = 
"sha256:2296356b5c9605b73ed6a52660b538787094dae13786ba53080595d52df13a98"},
+    {file = "grpcio-1.54.2-cp39-cp39-macosx_10_10_universal2.whl", hash = 
"sha256:c72956972e4b508dd39fdc7646637a791a9665b478e768ffa5f4fe42123d5de1"},
+    {file = "grpcio-1.54.2-cp39-cp39-manylinux_2_17_aarch64.whl", hash = 
"sha256:9bdbb7624d65dc0ed2ed8e954e79ab1724526f09b1efa88dcd9a1815bf28be5f"},
+    {file = 
"grpcio-1.54.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = 
"sha256:4c44e1a765b31e175c391f22e8fc73b2a2ece0e5e6ff042743d8109b5d2eff9f"},
+    {file = 
"grpcio-1.54.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash 
= "sha256:5cc928cfe6c360c1df636cf7991ab96f059666ac7b40b75a769410cc6217df9c"},
+    {file = "grpcio-1.54.2-cp39-cp39-musllinux_1_1_i686.whl", hash = 
"sha256:a08920fa1a97d4b8ee5db2f31195de4a9def1a91bc003544eb3c9e6b8977960a"},
+    {file = "grpcio-1.54.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = 
"sha256:4864f99aac207e3e45c5e26c6cbb0ad82917869abc2f156283be86c05286485c"},
+    {file = "grpcio-1.54.2-cp39-cp39-win32.whl", hash = 
"sha256:b38b3de8cff5bc70f8f9c615f51b48eff7313fc9aca354f09f81b73036e7ddfa"},
+    {file = "grpcio-1.54.2-cp39-cp39-win_amd64.whl", hash = 
"sha256:be48496b0e00460717225e7680de57c38be1d8629dc09dadcd1b3389d70d942b"},
+    {file = "grpcio-1.54.2.tar.gz", hash = 
"sha256:50a9f075eeda5097aa9a182bb3877fe1272875e45370368ac0ee16ab9e22d019"},
+]
+
+[package.extras]
+protobuf = ["grpcio-tools (>=1.54.2)"]
+
+[[package]]
+name = "grpcio-tools"
+version = "1.54.2"
+description = "Protobuf code generator for gRPC"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "grpcio-tools-1.54.2.tar.gz", hash = 
"sha256:e11c2c2aee53f340992e8e4d6a59172cbbbd0193f1351de98c4f810a5041d5ca"},
+    {file = "grpcio_tools-1.54.2-cp310-cp310-linux_armv7l.whl", hash = 
"sha256:2b96f5f17d3156058be247fd25b062b4768138665694c00b056659618b8fb418"},
+    {file = "grpcio_tools-1.54.2-cp310-cp310-macosx_12_0_universal2.whl", hash 
= "sha256:11939c9a8a39bd4815c7e88cb2fee48e1948775b59dbb06de8fcae5991e84f9e"},
+    {file = "grpcio_tools-1.54.2-cp310-cp310-manylinux_2_17_aarch64.whl", hash 
= "sha256:129de5579f95d6a55dde185f188b4cbe19d1e2f1471425431d9930c31d300d70"},
+    {file = 
"grpcio_tools-1.54.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", 
hash = 
"sha256:c4128c01cd6f5ea8f7c2db405dbfd8582cd967d36e6fa0952565436633b0e591"},
+    {file = 
"grpcio_tools-1.54.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
 hash = 
"sha256:e5c7292dd899ad8fa09a2be96719648cee37b17909fe8c12007e3bff58ebee61"},
+    {file = "grpcio_tools-1.54.2-cp310-cp310-musllinux_1_1_i686.whl", hash = 
"sha256:5ef30c2dbc63c1e0a462423ca4f95001814d26ef4fe66208e53fcf220ea3b717"},
+    {file = "grpcio_tools-1.54.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = 
"sha256:4abfc1892380abe6cef381eab86f9350cbd703bfe5d834095aa66fd91c886b6d"},
+    {file = "grpcio_tools-1.54.2-cp310-cp310-win32.whl", hash = 
"sha256:9acf443dcf6f68fbea3b7fb519e1716e014db1a561939f5aecc4abda74e4015d"},
+    {file = "grpcio_tools-1.54.2-cp310-cp310-win_amd64.whl", hash = 
"sha256:21b9d2dee80f3f77e4097252e7f0db89772335a7300b72ab3d2e5c280872b1db"},
+    {file = "grpcio_tools-1.54.2-cp311-cp311-linux_armv7l.whl", hash = 
"sha256:7b24fbab9e7598518ce4549e066df00aab79c2bf9bedcdde23fb5ef6a3cf532f"},
+    {file = "grpcio_tools-1.54.2-cp311-cp311-macosx_10_10_universal2.whl", 
hash = 
"sha256:7baa210c20f71a242d9ae0e02734628f6948e8bee3bf538647894af427d28800"},
+    {file = "grpcio_tools-1.54.2-cp311-cp311-manylinux_2_17_aarch64.whl", hash 
= "sha256:e3d0e5188ff8dbaddac2ee44731d36f09c4eccd3eac7328e547862c44f75cacd"},
+    {file = 
"grpcio_tools-1.54.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", 
hash = 
"sha256:27671c68c7e0e3c5ff9967f5500799f65a04e7b153b8ce10243c87c43199039d"},
+    {file = 
"grpcio_tools-1.54.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
 hash = 
"sha256:f39d8e8806b8857fb473ca6a9c7bd800b0673dfdb7283ff569af0345a222f32c"},
+    {file = "grpcio_tools-1.54.2-cp311-cp311-musllinux_1_1_i686.whl", hash = 
"sha256:8e4c5a48f7b2e8798ce381498ee7b9a83c65b87ae66ee5022387394e5eb51771"},
+    {file = "grpcio_tools-1.54.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = 
"sha256:4f285f8ef3de422717a36bd372239ae778b8cc112ce780ca3c7fe266dadc49fb"},
+    {file = "grpcio_tools-1.54.2-cp311-cp311-win32.whl", hash = 
"sha256:0f952c8a5c47e9204fe8959f7e9add149e660f6579d67cf65024c32736d34caf"},
+    {file = "grpcio_tools-1.54.2-cp311-cp311-win_amd64.whl", hash = 
"sha256:3237149beec39e897fd62cef4aa1e1cd9422d7a95661d24bd0a79200b167e730"},
+    {file = "grpcio_tools-1.54.2-cp37-cp37m-linux_armv7l.whl", hash = 
"sha256:0ab1b323905d449298523db5d34fa5bf5fffd645bd872b25598e2f8a01f0ea39"},
+    {file = "grpcio_tools-1.54.2-cp37-cp37m-macosx_10_10_universal2.whl", hash 
= "sha256:7d7e6e8d62967b3f037f952620cb7381cc39a4bd31790c75fcfba56cc975d70b"},
+    {file = "grpcio_tools-1.54.2-cp37-cp37m-manylinux_2_17_aarch64.whl", hash 
= "sha256:7f4624ef2e76a3a5313c4e61a81be38bcc16b59a68a85d30758b84cd2102b161"},
+    {file = 
"grpcio_tools-1.54.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", 
hash = 
"sha256:e543f457935ba7b763b121f1bf893974393b4d30065042f947f85a8d81081b80"},
+    {file = 
"grpcio_tools-1.54.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
 hash = 
"sha256:0239b929eb8b3b30b2397eef3b9abb245087754d77c3721e3be43c44796de87d"},
+    {file = "grpcio_tools-1.54.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = 
"sha256:0de05c7698c655e9a240dc34ae91d6017b93143ac89e5b20046d7ca3bd09c27c"},
+    {file = "grpcio_tools-1.54.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = 
"sha256:a3ce0b98fb581c471424d2cda45120f57658ed97677c6fec4d6decf5d7c1b976"},
+    {file = "grpcio_tools-1.54.2-cp37-cp37m-win_amd64.whl", hash = 
"sha256:37393ef90674964175923afe3859fc5a208e1ece565f642b4f76a8c0224a0993"},
+    {file = "grpcio_tools-1.54.2-cp38-cp38-linux_armv7l.whl", hash = 
"sha256:8e4531267736d88fde1022b36dd42ed8163e3575bcbd12bfed96662872aa93fe"},
+    {file = "grpcio_tools-1.54.2-cp38-cp38-macosx_10_10_universal2.whl", hash 
= "sha256:a0b7049814442f918b522d66b1d015286afbeb9e6d141af54bbfafe31710a3c8"},
+    {file = "grpcio_tools-1.54.2-cp38-cp38-manylinux_2_17_aarch64.whl", hash = 
"sha256:b80585e06c4f0082327eb5c9ad96fbdb2b0e7c14971ea5099fe78c22f4608451"},
+    {file = 
"grpcio_tools-1.54.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", 
hash = 
"sha256:39fd530cfdf58dc05125775cc233b05554d553d27478f14ae5fd8a6306f0cb28"},
+    {file = 
"grpcio_tools-1.54.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", 
hash = 
"sha256:3bb9ec4aea0f2b3006fb002fa59e5c10f92b48fc374619fbffd14d2b0e388c3e"},
+    {file = "grpcio_tools-1.54.2-cp38-cp38-musllinux_1_1_i686.whl", hash = 
"sha256:d512de051342a576bb89777476d13c5266d9334cf4badb6468aed9dc8f5bdec1"},
+    {file = "grpcio_tools-1.54.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = 
"sha256:1b8ee3099c51ce987fa8a08e6b93fc342b10228415dd96b5c0caa0387f636a6f"},
+    {file = "grpcio_tools-1.54.2-cp38-cp38-win32.whl", hash = 
"sha256:6037f123905dc0141f7c8383ca616ef0195e79cd3b4d82faaee789d4045e891b"},
+    {file = "grpcio_tools-1.54.2-cp38-cp38-win_amd64.whl", hash = 
"sha256:10dd41862f579d185c60f629b5ee89103e216f63b576079d258d974d980bad87"},
+    {file = "grpcio_tools-1.54.2-cp39-cp39-linux_armv7l.whl", hash = 
"sha256:f6787d07fdab31a32c433c1ba34883dea6559d8a3fbe08fb93d834ca34136b71"},
+    {file = "grpcio_tools-1.54.2-cp39-cp39-macosx_10_10_universal2.whl", hash 
= "sha256:21b1467e31e44429d2a78b50135c9cdbd4b8f6d3b5cd548bc98985d3bdc352d0"},
+    {file = "grpcio_tools-1.54.2-cp39-cp39-manylinux_2_17_aarch64.whl", hash = 
"sha256:30a49b8b168aced2a4ff40959e6c4383ad6cfd7a20839a47a215e9837eb722dc"},
+    {file = 
"grpcio_tools-1.54.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", 
hash = 
"sha256:8742122782953d2fd038f0a199f047a24e941cc9718b1aac90876dbdb7167739"},
+    {file = 
"grpcio_tools-1.54.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", 
hash = 
"sha256:503ef1351c62fb1d6747eaf74932b609d8fdd4345b3591ef910adef8fa9969d0"},
+    {file = "grpcio_tools-1.54.2-cp39-cp39-musllinux_1_1_i686.whl", hash = 
"sha256:72d15de4c4b6a764a76c4ae69d99c35f7a0751223688c3f7e62dfa95eb4f61be"},
+    {file = "grpcio_tools-1.54.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = 
"sha256:df079479fb1b9e488334312e35ebbf30cbf5ecad6c56599f1a961800b33ab7c1"},
+    {file = "grpcio_tools-1.54.2-cp39-cp39-win32.whl", hash = 
"sha256:49c2846dcc4803476e839d8bd4db8845e928f19130e0ea86121f2d1f43d2b452"},
+    {file = "grpcio_tools-1.54.2-cp39-cp39-win_amd64.whl", hash = 
"sha256:b82ca472db9c914c44e39a41e9e8bd3ed724523dd7aff5ce37592b8d16920ed9"},
+]
+
+[package.dependencies]
+grpcio = ">=1.54.2"
+protobuf = ">=4.21.6,<5.0dev"
+setuptools = "*"
+
+[[package]]
+name = "importlib-metadata"
+version = "6.6.0"
+description = "Read metadata from Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = 
"sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
+    {file = "importlib_metadata-6.6.0.tar.gz", hash = 
"sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
+]
+
+[package.dependencies]
+typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
+zipp = ">=0.5"
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", 
"rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+perf = ["ipython"]
+testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", 
"packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", 
"pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", 
"pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
+
+[[package]]
+name = "iniconfig"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "iniconfig-2.0.0-py3-none-any.whl", hash = 
"sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+    {file = "iniconfig-2.0.0.tar.gz", hash = 
"sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
+]
+
+[[package]]
+name = "packaging"
+version = "23.1"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "packaging-23.1-py3-none-any.whl", hash = 
"sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
+    {file = "packaging-23.1.tar.gz", hash = 
"sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
+]
+
+[[package]]
+name = "pluggy"
+version = "1.0.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = 
"sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
+    {file = "pluggy-1.0.0.tar.gz", hash = 
"sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+]
+
+[package.dependencies]
+importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "protobuf"
+version = "4.23.2"
+description = ""
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "protobuf-4.23.2-cp310-abi3-win32.whl", hash = 
"sha256:384dd44cb4c43f2ccddd3645389a23ae61aeb8cfa15ca3a0f60e7c3ea09b28b3"},
+    {file = "protobuf-4.23.2-cp310-abi3-win_amd64.whl", hash = 
"sha256:09310bce43353b46d73ba7e3bca78273b9bc50349509b9698e64d288c6372c2a"},
+    {file = "protobuf-4.23.2-cp37-abi3-macosx_10_9_universal2.whl", hash = 
"sha256:b2cfab63a230b39ae603834718db74ac11e52bccaaf19bf20f5cce1a84cf76df"},
+    {file = "protobuf-4.23.2-cp37-abi3-manylinux2014_aarch64.whl", hash = 
"sha256:c52cfcbfba8eb791255edd675c1fe6056f723bf832fa67f0442218f8817c076e"},
+    {file = "protobuf-4.23.2-cp37-abi3-manylinux2014_x86_64.whl", hash = 
"sha256:86df87016d290143c7ce3be3ad52d055714ebaebb57cc659c387e76cfacd81aa"},
+    {file = "protobuf-4.23.2-cp37-cp37m-win32.whl", hash = 
"sha256:281342ea5eb631c86697e1e048cb7e73b8a4e85f3299a128c116f05f5c668f8f"},
+    {file = "protobuf-4.23.2-cp37-cp37m-win_amd64.whl", hash = 
"sha256:ce744938406de1e64b91410f473736e815f28c3b71201302612a68bf01517fea"},
+    {file = "protobuf-4.23.2-cp38-cp38-win32.whl", hash = 
"sha256:6c081863c379bb1741be8f8193e893511312b1d7329b4a75445d1ea9955be69e"},
+    {file = "protobuf-4.23.2-cp38-cp38-win_amd64.whl", hash = 
"sha256:25e3370eda26469b58b602e29dff069cfaae8eaa0ef4550039cc5ef8dc004511"},
+    {file = "protobuf-4.23.2-cp39-cp39-win32.whl", hash = 
"sha256:efabbbbac1ab519a514579ba9ec52f006c28ae19d97915951f69fa70da2c9e91"},
+    {file = "protobuf-4.23.2-cp39-cp39-win_amd64.whl", hash = 
"sha256:54a533b971288af3b9926e53850c7eb186886c0c84e61daa8444385a4720297f"},
+    {file = "protobuf-4.23.2-py3-none-any.whl", hash = 
"sha256:8da6070310d634c99c0db7df48f10da495cc283fd9e9234877f0cd182d43ab7f"},
+    {file = "protobuf-4.23.2.tar.gz", hash = 
"sha256:20874e7ca4436f683b64ebdbee2129a5a2c301579a67d1a7dda2cdf62fb7f5f7"},
+]
+
+[[package]]
+name = "pytest"
+version = "7.3.1"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "pytest-7.3.1-py3-none-any.whl", hash = 
"sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"},
+    {file = "pytest-7.3.1.tar.gz", hash = 
"sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < 
\"3.11\""}
+importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", 
"nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
+
+[[package]]
+name = "setuptools"
+version = "67.8.0"
+description = "Easily download, build, install, upgrade, and uninstall Python 
packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "setuptools-67.8.0-py3-none-any.whl", hash = 
"sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"},
+    {file = "setuptools-67.8.0.tar.gz", hash = 
"sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"},
+]
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", 
"pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", 
"sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", 
"sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", 
"sphinxcontrib-towncrier"]
+testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", 
"ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip 
(>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", 
"pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", 
"pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", 
"pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs 
(>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", 
"tomli", "virtualenv (>=13.0.0)", "wheel"]
+
+[[package]]
+name = "tomli"
+version = "2.0.1"
+description = "A lil' TOML parser"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "tomli-2.0.1-py3-none-any.whl", hash = 
"sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+    {file = "tomli-2.0.1.tar.gz", hash = 
"sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.6.2"
+description = "Backported and Experimental Type Hints for Python 3.7+"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "typing_extensions-4.6.2-py3-none-any.whl", hash = 
"sha256:3a8b36f13dd5fdc5d1b16fe317f5668545de77fa0b8e02006381fd49d731ab98"},
+    {file = "typing_extensions-4.6.2.tar.gz", hash = 
"sha256:06006244c70ac8ee83fa8282cb188f697b8db25bc8b4df07be1873c43897060c"},
+]
+
+[[package]]
+name = "zipp"
+version = "3.15.0"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "zipp-3.15.0-py3-none-any.whl", hash = 
"sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
+    {file = "zipp-3.15.0.tar.gz", hash = 
"sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
+]
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", 
"rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", 
"more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs 
(>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy 
(>=0.9.1)"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.7"
+content-hash = 
"8452cc04f16254585b86b05703ed525c20f7c471f180da580e95f26324df7f55"
diff --git a/python/protocol/definition_pb2.py 
b/python/protocol/definition_pb2.py
deleted file mode 100644
index ef2a38fb..00000000
--- a/python/protocol/definition_pb2.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: definition.proto
-"""Generated protocol buffer code."""
-from google.protobuf.internal import builder as _builder
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import descriptor_pool as _descriptor_pool
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-from google.protobuf import timestamp_pb2 as 
google_dot_protobuf_dot_timestamp__pb2
-from google.protobuf import duration_pb2 as 
google_dot_protobuf_dot_duration__pb2
-
-
-DESCRIPTOR = 
_descriptor_pool.Default().AddSerializedFile(b'\n\x10\x64\x65\x66inition.proto\x12\x12\x61pache.rocketmq.v2\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/duration.proto\"T\n\x10\x46ilterExpression\x12,\n\x04type\x18\x01
 \x01(\x0e\x32\x1e.apache.rocketmq.v2.FilterType\x12\x12\n\nexpression\x18\x02 
\x01(\t\"\xbb\x01\n\x0bRetryPolicy\x12\x14\n\x0cmax_attempts\x18\x01 
\x01(\x05\x12\x45\n\x13\x65xponential_backoff\x18\x02 
\x01(\x0b\x32&.apache.rocketmq.v2.Exponent [...]
-
-_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
-_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'definition_pb2', 
globals())
-if _descriptor._USE_C_DESCRIPTORS == False:
-
-  DESCRIPTOR._options = None
-  DESCRIPTOR._serialized_options = 
b'\n\022apache.rocketmq.v2B\010MQDomainP\001\240\001\001\330\001\001\252\002\022Apache.Rocketmq.V2'
-  _MESSAGE_USERPROPERTIESENTRY._options = None
-  _MESSAGE_USERPROPERTIESENTRY._serialized_options = b'8\001'
-  _TRANSACTIONRESOLUTION._serialized_start=2752
-  _TRANSACTIONRESOLUTION._serialized_end=2841
-  _TRANSACTIONSOURCE._serialized_start=2843
-  _TRANSACTIONSOURCE._serialized_end=2930
-  _PERMISSION._serialized_start=2932
-  _PERMISSION._serialized_end=3019
-  _FILTERTYPE._serialized_start=3021
-  _FILTERTYPE._serialized_end=3080
-  _ADDRESSSCHEME._serialized_start=3082
-  _ADDRESSSCHEME._serialized_end=3166
-  _MESSAGETYPE._serialized_start=3168
-  _MESSAGETYPE._serialized_end=3261
-  _DIGESTTYPE._serialized_start=3263
-  _DIGESTTYPE._serialized_end=3334
-  _CLIENTTYPE._serialized_start=3336
-  _CLIENTTYPE._serialized_end=3431
-  _ENCODING._serialized_start=3433
-  _ENCODING._serialized_end=3493
-  _CODE._serialized_start=3496
-  _CODE._serialized_end=4746
-  _LANGUAGE._serialized_start=4748
-  _LANGUAGE._serialized_end=4838
-  _FILTEREXPRESSION._serialized_start=105
-  _FILTEREXPRESSION._serialized_end=189
-  _RETRYPOLICY._serialized_start=192
-  _RETRYPOLICY._serialized_end=379
-  _EXPONENTIALBACKOFF._serialized_start=381
-  _EXPONENTIALBACKOFF._serialized_end=505
-  _CUSTOMIZEDBACKOFF._serialized_start=507
-  _CUSTOMIZEDBACKOFF._serialized_end=567
-  _RESOURCE._serialized_start=569
-  _RESOURCE._serialized_end=621
-  _SUBSCRIPTIONENTRY._serialized_start=623
-  _SUBSCRIPTIONENTRY._serialized_end=745
-  _ADDRESS._serialized_start=747
-  _ADDRESS._serialized_end=784
-  _ENDPOINTS._serialized_start=786
-  _ENDPOINTS._serialized_end=896
-  _BROKER._serialized_start=898
-  _BROKER._serialized_end=982
-  _MESSAGEQUEUE._serialized_start=985
-  _MESSAGEQUEUE._serialized_end=1215
-  _DIGEST._serialized_start=1217
-  _DIGEST._serialized_end=1289
-  _SYSTEMPROPERTIES._serialized_start=1292
-  _SYSTEMPROPERTIES._serialized_end=2240
-  _MESSAGE._serialized_start=2243
-  _MESSAGE._serialized_end=2505
-  _MESSAGE_USERPROPERTIESENTRY._serialized_start=2452
-  _MESSAGE_USERPROPERTIESENTRY._serialized_end=2505
-  _ASSIGNMENT._serialized_start=2507
-  _ASSIGNMENT._serialized_end=2576
-  _STATUS._serialized_start=2578
-  _STATUS._serialized_end=2643
-  _UA._serialized_start=2645
-  _UA._serialized_end=2750
-# @@protoc_insertion_point(module_scope)
diff --git a/python/protocol/service_pb2.py b/python/protocol/service_pb2.py
deleted file mode 100644
index 3b5ee27d..00000000
--- a/python/protocol/service_pb2.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-# 
-#     http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: service.proto
-"""Generated protocol buffer code."""
-from google.protobuf.internal import builder as _builder
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import descriptor_pool as _descriptor_pool
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-from google.protobuf import duration_pb2 as 
google_dot_protobuf_dot_duration__pb2
-from google.protobuf import timestamp_pb2 as 
google_dot_protobuf_dot_timestamp__pb2
-import definition_pb2 as definition__pb2
-
-
-DESCRIPTOR = 
_descriptor_pool.Default().AddSerializedFile(b'\n\rservice.proto\x12\x12\x61pache.rocketmq.v2\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x10\x64\x65\x66inition.proto\"r\n\x11QueryRouteRequest\x12+\n\x05topic\x18\x01
 \x01(\x0b\x32\x1c.apache.rocketmq.v2.Resource\x12\x30\n\tendpoints\x18\x02 
\x01(\x0b\x32\x1d.apache.rocketmq.v2.Endpoints\"z\n\x12QueryRouteResponse\x12*\n\x06status\x18\x01
 \x01(\x0b\x32\x1a.apache.rocketmq.v2.Status\x12\x38 [...]
-
-_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
-_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'service_pb2', globals())
-if _descriptor._USE_C_DESCRIPTORS == False:
-
-  DESCRIPTOR._options = None
-  DESCRIPTOR._serialized_options = 
b'\n\022apache.rocketmq.v2B\tMQServiceP\001\240\001\001\330\001\001\252\002\022Apache.Rocketmq.V2'
-  _QUERYROUTEREQUEST._serialized_start=120
-  _QUERYROUTEREQUEST._serialized_end=234
-  _QUERYROUTERESPONSE._serialized_start=236
-  _QUERYROUTERESPONSE._serialized_end=358
-  _SENDMESSAGEREQUEST._serialized_start=360
-  _SENDMESSAGEREQUEST._serialized_end=427
-  _SENDRESULTENTRY._serialized_start=429
-  _SENDRESULTENTRY._serialized_end=550
-  _SENDMESSAGERESPONSE._serialized_start=552
-  _SENDMESSAGERESPONSE._serialized_end=671
-  _QUERYASSIGNMENTREQUEST._serialized_start=674
-  _QUERYASSIGNMENTREQUEST._serialized_end=838
-  _QUERYASSIGNMENTRESPONSE._serialized_start=840
-  _QUERYASSIGNMENTRESPONSE._serialized_end=962
-  _RECEIVEMESSAGEREQUEST._serialized_start=965
-  _RECEIVEMESSAGEREQUEST._serialized_end=1278
-  _RECEIVEMESSAGERESPONSE._serialized_start=1281
-  _RECEIVEMESSAGERESPONSE._serialized_end=1468
-  _ACKMESSAGEENTRY._serialized_start=1470
-  _ACKMESSAGEENTRY._serialized_end=1531
-  _ACKMESSAGEREQUEST._serialized_start=1534
-  _ACKMESSAGEREQUEST._serialized_end=1697
-  _ACKMESSAGERESULTENTRY._serialized_start=1699
-  _ACKMESSAGERESULTENTRY._serialized_end=1810
-  _ACKMESSAGERESPONSE._serialized_start=1812
-  _ACKMESSAGERESPONSE._serialized_end=1936
-  _FORWARDMESSAGETODEADLETTERQUEUEREQUEST._serialized_start=1939
-  _FORWARDMESSAGETODEADLETTERQUEUEREQUEST._serialized_end=2170
-  _FORWARDMESSAGETODEADLETTERQUEUERESPONSE._serialized_start=2172
-  _FORWARDMESSAGETODEADLETTERQUEUERESPONSE._serialized_end=2257
-  _HEARTBEATREQUEST._serialized_start=2260
-  _HEARTBEATREQUEST._serialized_end=2391
-  _HEARTBEATRESPONSE._serialized_start=2393
-  _HEARTBEATRESPONSE._serialized_end=2456
-  _ENDTRANSACTIONREQUEST._serialized_start=2459
-  _ENDTRANSACTIONREQUEST._serialized_end=2712
-  _ENDTRANSACTIONRESPONSE._serialized_start=2714
-  _ENDTRANSACTIONRESPONSE._serialized_end=2782
-  _PRINTTHREADSTACKTRACECOMMAND._serialized_start=2784
-  _PRINTTHREADSTACKTRACECOMMAND._serialized_end=2829
-  _THREADSTACKTRACE._serialized_start=2831
-  _THREADSTACKTRACE._serialized_end=2920
-  _VERIFYMESSAGECOMMAND._serialized_start=2922
-  _VERIFYMESSAGECOMMAND._serialized_end=3005
-  _VERIFYMESSAGERESULT._serialized_start=3007
-  _VERIFYMESSAGERESULT._serialized_end=3043
-  _RECOVERORPHANEDTRANSACTIONCOMMAND._serialized_start=3045
-  _RECOVERORPHANEDTRANSACTIONCOMMAND._serialized_end=3150
-  _PUBLISHING._serialized_start=3152
-  _PUBLISHING._serialized_end=3264
-  _SUBSCRIPTION._serialized_start=3267
-  _SUBSCRIPTION._serialized_end=3574
-  _METRIC._serialized_start=3576
-  _METRIC._serialized_end=3665
-  _SETTINGS._serialized_start=3668
-  _SETTINGS._serialized_end=4196
-  _TELEMETRYCOMMAND._serialized_start=4199
-  _TELEMETRYCOMMAND._serialized_end=4753
-  _NOTIFYCLIENTTERMINATIONREQUEST._serialized_start=4755
-  _NOTIFYCLIENTTERMINATIONREQUEST._serialized_end=4847
-  _NOTIFYCLIENTTERMINATIONRESPONSE._serialized_start=4849
-  _NOTIFYCLIENTTERMINATIONRESPONSE._serialized_end=4926
-  _CHANGEINVISIBLEDURATIONREQUEST._serialized_start=4929
-  _CHANGEINVISIBLEDURATIONREQUEST._serialized_end=5150
-  _CHANGEINVISIBLEDURATIONRESPONSE._serialized_start=5152
-  _CHANGEINVISIBLEDURATIONRESPONSE._serialized_end=5253
-  _MESSAGINGSERVICE._serialized_start=5256
-  _MESSAGINGSERVICE._serialized_end=6504
-# @@protoc_insertion_point(module_scope)
diff --git a/python/pyproject.toml b/python/pyproject.toml
new file mode 100644
index 00000000..ff017178
--- /dev/null
+++ b/python/pyproject.toml
@@ -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.
+
+[tool.poetry]
+name = "rocketmq"
+version = "0.1.0rc1"
+description = "RocketMQ Python Client"
+authors = ["RocketMQ Authors"]
+readme = "README.md"
+packages = [{ include = "rocketmq" }]
+
+[tool.poetry.dependencies]
+python = "^3.7"
+grpcio = "^1.50.0"
+grpcio-tools = "^1.50.0"
+certifi = "^2023.5.7"
+
+[tool.poetry.dev-dependencies]
+pytest = "^7.0.07"
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
+
+[tool.black]
+line-length = 88
+target-version = ['py37']
+include = '\.pyi?$'
+# 'extend-exclude' excludes files or directories in addition to the defaults
+extend-exclude = '''
+# A regex preceded with ^/ will apply only to files and directories
+# in the root of the project.
+(
+  ^/foo.py    # exclude a file named foo.py in the root of the project
+  | .*_pb2.*  # exclude autogenerated Protocol Buffer files anywhere in the 
project
+)
+'''
diff --git a/python/requirements.txt b/python/requirements.txt
deleted file mode 100644
index b63dce08..00000000
--- a/python/requirements.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-grpc-interceptor==0.15.1
-grpcio==1.51.3
-grpcio-tools==1.51.3
\ No newline at end of file
diff --git a/python/protocol/definition_pb2_grpc.py 
b/python/rocketmq/__init__.py
similarity index 54%
copy from python/protocol/definition_pb2_grpc.py
copy to python/rocketmq/__init__.py
index 2cd6c817..3fc459fd 100644
--- a/python/protocol/definition_pb2_grpc.py
+++ b/python/rocketmq/__init__.py
@@ -4,16 +4,35 @@
 # The ASF licenses this file to You under the Apache License, Version 2.0
 # (the "License"); you may not use this file except in compliance with
 # the License.  You may obtain a copy of the License at
-# 
+#
 #     http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT 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 gRPC Python protocol compiler plugin. DO NOT EDIT!
-"""Client and server classes corresponding to protobuf-defined services."""
-import grpc
+import logging
+import os
 
+logger = logging.getLogger("rocketmqlogger")
+logger.setLevel(logging.DEBUG)
+
+log_path = os.path.join(
+    os.path.expanduser("~"), "logs", "rocketmq", "rocketmq-client.log"
+)
+file_handler = logging.FileHandler(log_path)
+file_handler.setLevel(logging.DEBUG)
+
+console_handler = logging.StreamHandler()
+console_handler.setLevel(logging.DEBUG)
+
+formatter = logging.Formatter(
+    "%(asctime)s [%(levelname)s] [%(process)d] 
[%(filename)s#%(funcName)s:%(lineno)d] %(message)s"
+)
+file_handler.setFormatter(formatter)
+console_handler.setFormatter(formatter)
+
+logger.addHandler(file_handler)
+logger.addHandler(console_handler)
diff --git a/python/protocol/__init__.py b/python/rocketmq/foo.py
similarity index 93%
copy from python/protocol/__init__.py
copy to python/rocketmq/foo.py
index 2bbe709e..a56f4030 100644
--- a/python/protocol/__init__.py
+++ b/python/rocketmq/foo.py
@@ -4,11 +4,13 @@
 # The ASF licenses this file to You under the Apache License, Version 2.0
 # (the "License"); you may not use this file except in compliance with
 # the License.  You may obtain a copy of the License at
-# 
+#
 #     http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT 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
+# limitations under the License.
+
+bar = 1234
diff --git a/python/client/message/message_id_codec.py 
b/python/rocketmq/message_id_codec.py
similarity index 100%
rename from python/client/message/message_id_codec.py
rename to python/rocketmq/message_id_codec.py
diff --git a/python/protocol/__init__.py b/python/rocketmq/protocol/__init__.py
similarity index 95%
copy from python/protocol/__init__.py
copy to python/rocketmq/protocol/__init__.py
index 2bbe709e..ae1e83ee 100644
--- a/python/protocol/__init__.py
+++ b/python/rocketmq/protocol/__init__.py
@@ -4,11 +4,11 @@
 # The ASF licenses this file to You under the Apache License, Version 2.0
 # (the "License"); you may not use this file except in compliance with
 # the License.  You may obtain a copy of the License at
-# 
+#
 #     http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT 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
+# limitations under the License.
diff --git a/python/protocol/admin_pb2.py 
b/python/rocketmq/protocol/admin_pb2.py
similarity index 57%
rename from python/protocol/admin_pb2.py
rename to python/rocketmq/protocol/admin_pb2.py
index 20f5ab05..bb49bfc1 100644
--- a/python/protocol/admin_pb2.py
+++ b/python/rocketmq/protocol/admin_pb2.py
@@ -4,9 +4,9 @@
 # The ASF licenses this file to You under the Apache License, Version 2.0
 # (the "License"); you may not use this file except in compliance with
 # the License.  You may obtain a copy of the License at
-# 
+#
 #     http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -15,7 +15,7 @@
 
 # -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: admin.proto
+# source: apache/rocketmq/v2/admin.proto
 """Generated protocol buffer code."""
 from google.protobuf.internal import builder as _builder
 from google.protobuf import descriptor as _descriptor
@@ -28,20 +28,20 @@ _sym_db = _symbol_database.Default()
 
 
 
-DESCRIPTOR = 
_descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x61\x64min.proto\x12\x12\x61pache.rocketmq.v2\"\x95\x01\n\x15\x43hangeLogLevelRequest\x12>\n\x05level\x18\x01
 
\x01(\x0e\x32/.apache.rocketmq.v2.ChangeLogLevelRequest.Level\"<\n\x05Level\x12\t\n\x05TRACE\x10\x00\x12\t\n\x05\x44\x45\x42UG\x10\x01\x12\x08\n\x04INFO\x10\x02\x12\x08\n\x04WARN\x10\x03\x12\t\n\x05\x45RROR\x10\x04\"(\n\x16\x43hangeLogLevelResponse\x12\x0e\n\x06remark\x18\x01
 \x01(\t2r\n\x05\x41\x64min\x12i\n\x0e\ [...]
+DESCRIPTOR = 
_descriptor_pool.Default().AddSerializedFile(b'\n\x1e\x61pache/rocketmq/v2/admin.proto\x12\x12\x61pache.rocketmq.v2\"\x95\x01\n\x15\x43hangeLogLevelRequest\x12>\n\x05level\x18\x01
 
\x01(\x0e\x32/.apache.rocketmq.v2.ChangeLogLevelRequest.Level\"<\n\x05Level\x12\t\n\x05TRACE\x10\x00\x12\t\n\x05\x44\x45\x42UG\x10\x01\x12\x08\n\x04INFO\x10\x02\x12\x08\n\x04WARN\x10\x03\x12\t\n\x05\x45RROR\x10\x04\"(\n\x16\x43hangeLogLevelResponse\x12\x0e\n\x06remark\x18\x01
 \x01(\t2r\n\x05\x41\x6 [...]
 
 _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
-_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'admin_pb2', globals())
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 
'apache.rocketmq.v2.admin_pb2', globals())
 if _descriptor._USE_C_DESCRIPTORS == False:
 
   DESCRIPTOR._options = None
   DESCRIPTOR._serialized_options = 
b'\n\022apache.rocketmq.v2B\007MQAdminP\001\240\001\001\330\001\001\370\001\001\252\002\022Apache.Rocketmq.V2'
-  _CHANGELOGLEVELREQUEST._serialized_start=36
-  _CHANGELOGLEVELREQUEST._serialized_end=185
-  _CHANGELOGLEVELREQUEST_LEVEL._serialized_start=125
-  _CHANGELOGLEVELREQUEST_LEVEL._serialized_end=185
-  _CHANGELOGLEVELRESPONSE._serialized_start=187
-  _CHANGELOGLEVELRESPONSE._serialized_end=227
-  _ADMIN._serialized_start=229
-  _ADMIN._serialized_end=343
+  _CHANGELOGLEVELREQUEST._serialized_start=55
+  _CHANGELOGLEVELREQUEST._serialized_end=204
+  _CHANGELOGLEVELREQUEST_LEVEL._serialized_start=144
+  _CHANGELOGLEVELREQUEST_LEVEL._serialized_end=204
+  _CHANGELOGLEVELRESPONSE._serialized_start=206
+  _CHANGELOGLEVELRESPONSE._serialized_end=246
+  _ADMIN._serialized_start=248
+  _ADMIN._serialized_end=362
 # @@protoc_insertion_point(module_scope)
diff --git a/python/rocketmq/protocol/admin_pb2.pyi 
b/python/rocketmq/protocol/admin_pb2.pyi
new file mode 100644
index 00000000..b286d4a4
--- /dev/null
+++ b/python/rocketmq/protocol/admin_pb2.pyi
@@ -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.
+
+from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from typing import ClassVar as _ClassVar, Optional as _Optional, Union as 
_Union
+
+DESCRIPTOR: _descriptor.FileDescriptor
+
+class ChangeLogLevelRequest(_message.Message):
+    __slots__ = ["level"]
+    class Level(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+        __slots__ = []
+    DEBUG: ChangeLogLevelRequest.Level
+    ERROR: ChangeLogLevelRequest.Level
+    INFO: ChangeLogLevelRequest.Level
+    LEVEL_FIELD_NUMBER: _ClassVar[int]
+    TRACE: ChangeLogLevelRequest.Level
+    WARN: ChangeLogLevelRequest.Level
+    level: ChangeLogLevelRequest.Level
+    def __init__(self, level: _Optional[_Union[ChangeLogLevelRequest.Level, 
str]] = ...) -> None: ...
+
+class ChangeLogLevelResponse(_message.Message):
+    __slots__ = ["remark"]
+    REMARK_FIELD_NUMBER: _ClassVar[int]
+    remark: str
+    def __init__(self, remark: _Optional[str] = ...) -> None: ...
diff --git a/python/protocol/admin_pb2_grpc.py 
b/python/rocketmq/protocol/admin_pb2_grpc.py
similarity index 78%
rename from python/protocol/admin_pb2_grpc.py
rename to python/rocketmq/protocol/admin_pb2_grpc.py
index a43fea3f..6905975f 100644
--- a/python/protocol/admin_pb2_grpc.py
+++ b/python/rocketmq/protocol/admin_pb2_grpc.py
@@ -4,9 +4,9 @@
 # The ASF licenses this file to You under the Apache License, Version 2.0
 # (the "License"); you may not use this file except in compliance with
 # the License.  You may obtain a copy of the License at
-# 
+#
 #     http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,7 +17,7 @@
 """Client and server classes corresponding to protobuf-defined services."""
 import grpc
 
-import admin_pb2 as admin__pb2
+from protocol import admin_pb2 as apache_dot_rocketmq_dot_v2_dot_admin__pb2
 
 
 class AdminStub(object):
@@ -31,8 +31,8 @@ class AdminStub(object):
         """
         self.ChangeLogLevel = channel.unary_unary(
                 '/apache.rocketmq.v2.Admin/ChangeLogLevel',
-                
request_serializer=admin__pb2.ChangeLogLevelRequest.SerializeToString,
-                
response_deserializer=admin__pb2.ChangeLogLevelResponse.FromString,
+                
request_serializer=apache_dot_rocketmq_dot_v2_dot_admin__pb2.ChangeLogLevelRequest.SerializeToString,
+                
response_deserializer=apache_dot_rocketmq_dot_v2_dot_admin__pb2.ChangeLogLevelResponse.FromString,
                 )
 
 
@@ -50,8 +50,8 @@ def add_AdminServicer_to_server(servicer, server):
     rpc_method_handlers = {
             'ChangeLogLevel': grpc.unary_unary_rpc_method_handler(
                     servicer.ChangeLogLevel,
-                    
request_deserializer=admin__pb2.ChangeLogLevelRequest.FromString,
-                    
response_serializer=admin__pb2.ChangeLogLevelResponse.SerializeToString,
+                    
request_deserializer=apache_dot_rocketmq_dot_v2_dot_admin__pb2.ChangeLogLevelRequest.FromString,
+                    
response_serializer=apache_dot_rocketmq_dot_v2_dot_admin__pb2.ChangeLogLevelResponse.SerializeToString,
             ),
     }
     generic_handler = grpc.method_handlers_generic_handler(
@@ -75,7 +75,7 @@ class Admin(object):
             timeout=None,
             metadata=None):
         return grpc.experimental.unary_unary(request, target, 
'/apache.rocketmq.v2.Admin/ChangeLogLevel',
-            admin__pb2.ChangeLogLevelRequest.SerializeToString,
-            admin__pb2.ChangeLogLevelResponse.FromString,
+            
apache_dot_rocketmq_dot_v2_dot_admin__pb2.ChangeLogLevelRequest.SerializeToString,
+            
apache_dot_rocketmq_dot_v2_dot_admin__pb2.ChangeLogLevelResponse.FromString,
             options, channel_credentials,
             insecure, call_credentials, compression, wait_for_ready, timeout, 
metadata)
diff --git a/python/rocketmq/protocol/definition_pb2.py 
b/python/rocketmq/protocol/definition_pb2.py
new file mode 100644
index 00000000..9ad8bc6a
--- /dev/null
+++ b/python/rocketmq/protocol/definition_pb2.py
@@ -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.
+
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: apache/rocketmq/v2/definition.proto
+"""Generated protocol buffer code."""
+from google.protobuf.internal import builder as _builder
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+from google.protobuf import timestamp_pb2 as 
google_dot_protobuf_dot_timestamp__pb2
+from google.protobuf import duration_pb2 as 
google_dot_protobuf_dot_duration__pb2
+
+
+DESCRIPTOR = 
_descriptor_pool.Default().AddSerializedFile(b'\n#apache/rocketmq/v2/definition.proto\x12\x12\x61pache.rocketmq.v2\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/duration.proto\"T\n\x10\x46ilterExpression\x12,\n\x04type\x18\x01
 \x01(\x0e\x32\x1e.apache.rocketmq.v2.FilterType\x12\x12\n\nexpression\x18\x02 
\x01(\t\"\xbb\x01\n\x0bRetryPolicy\x12\x14\n\x0cmax_attempts\x18\x01 
\x01(\x05\x12\x45\n\x13\x65xponential_backoff\x18\x02 
\x01(\x0b\x32&.apache.rocketmq.v2.E [...]
+
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 
'apache.rocketmq.v2.definition_pb2', globals())
+if _descriptor._USE_C_DESCRIPTORS == False:
+
+  DESCRIPTOR._options = None
+  DESCRIPTOR._serialized_options = 
b'\n\022apache.rocketmq.v2B\010MQDomainP\001\240\001\001\330\001\001\252\002\022Apache.Rocketmq.V2'
+  _MESSAGE_USERPROPERTIESENTRY._options = None
+  _MESSAGE_USERPROPERTIESENTRY._serialized_options = b'8\001'
+  _TRANSACTIONRESOLUTION._serialized_start=3962
+  _TRANSACTIONRESOLUTION._serialized_end=4051
+  _TRANSACTIONSOURCE._serialized_start=4053
+  _TRANSACTIONSOURCE._serialized_end=4140
+  _PERMISSION._serialized_start=4142
+  _PERMISSION._serialized_end=4229
+  _FILTERTYPE._serialized_start=4231
+  _FILTERTYPE._serialized_end=4290
+  _ADDRESSSCHEME._serialized_start=4292
+  _ADDRESSSCHEME._serialized_end=4376
+  _MESSAGETYPE._serialized_start=4378
+  _MESSAGETYPE._serialized_end=4471
+  _DIGESTTYPE._serialized_start=4473
+  _DIGESTTYPE._serialized_end=4544
+  _CLIENTTYPE._serialized_start=4546
+  _CLIENTTYPE._serialized_end=4641
+  _ENCODING._serialized_start=4643
+  _ENCODING._serialized_end=4703
+  _CODE._serialized_start=4706
+  _CODE._serialized_end=5984
+  _LANGUAGE._serialized_start=5987
+  _LANGUAGE._serialized_end=6160
+  _FILTEREXPRESSION._serialized_start=124
+  _FILTEREXPRESSION._serialized_end=208
+  _RETRYPOLICY._serialized_start=211
+  _RETRYPOLICY._serialized_end=398
+  _EXPONENTIALBACKOFF._serialized_start=400
+  _EXPONENTIALBACKOFF._serialized_end=524
+  _CUSTOMIZEDBACKOFF._serialized_start=526
+  _CUSTOMIZEDBACKOFF._serialized_end=586
+  _RESOURCE._serialized_start=588
+  _RESOURCE._serialized_end=640
+  _SUBSCRIPTIONENTRY._serialized_start=642
+  _SUBSCRIPTIONENTRY._serialized_end=764
+  _ADDRESS._serialized_start=766
+  _ADDRESS._serialized_end=803
+  _ENDPOINTS._serialized_start=805
+  _ENDPOINTS._serialized_end=915
+  _BROKER._serialized_start=917
+  _BROKER._serialized_end=1001
+  _MESSAGEQUEUE._serialized_start=1004
+  _MESSAGEQUEUE._serialized_end=1234
+  _DIGEST._serialized_start=1236
+  _DIGEST._serialized_end=1308
+  _SYSTEMPROPERTIES._serialized_start=1311
+  _SYSTEMPROPERTIES._serialized_end=2350
+  _DEADLETTERQUEUE._serialized_start=2352
+  _DEADLETTERQUEUE._serialized_end=2404
+  _MESSAGE._serialized_start=2407
+  _MESSAGE._serialized_end=2669
+  _MESSAGE_USERPROPERTIESENTRY._serialized_start=2616
+  _MESSAGE_USERPROPERTIESENTRY._serialized_end=2669
+  _ASSIGNMENT._serialized_start=2671
+  _ASSIGNMENT._serialized_end=2740
+  _STATUS._serialized_start=2742
+  _STATUS._serialized_end=2807
+  _UA._serialized_start=2809
+  _UA._serialized_end=2914
+  _SETTINGS._serialized_start=2917
+  _SETTINGS._serialized_end=3445
+  _PUBLISHING._serialized_start=3447
+  _PUBLISHING._serialized_end=3559
+  _SUBSCRIPTION._serialized_start=3562
+  _SUBSCRIPTION._serialized_end=3869
+  _METRIC._serialized_start=3871
+  _METRIC._serialized_end=3960
+# @@protoc_insertion_point(module_scope)
diff --git a/python/rocketmq/protocol/definition_pb2.pyi 
b/python/rocketmq/protocol/definition_pb2.pyi
new file mode 100644
index 00000000..dcd0286b
--- /dev/null
+++ b/python/rocketmq/protocol/definition_pb2.pyi
@@ -0,0 +1,398 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 google.protobuf import timestamp_pb2 as _timestamp_pb2
+from google.protobuf import duration_pb2 as _duration_pb2
+from google.protobuf.internal import containers as _containers
+from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as 
_Mapping, Optional as _Optional, Union as _Union
+
+ADDRESS_SCHEME_UNSPECIFIED: AddressScheme
+BAD_REQUEST: Code
+CLIENT_ID_REQUIRED: Code
+CLIENT_TYPE_UNSPECIFIED: ClientType
+CODE_UNSPECIFIED: Code
+COMMIT: TransactionResolution
+CONSUMER_GROUP_NOT_FOUND: Code
+CPP: Language
+CRC32: DigestType
+DART: Language
+DELAY: MessageType
+DESCRIPTOR: _descriptor.FileDescriptor
+DIGEST_TYPE_UNSPECIFIED: DigestType
+DOMAIN_NAME: AddressScheme
+DOT_NET: Language
+ENCODING_UNSPECIFIED: Encoding
+FAILED_TO_CONSUME_MESSAGE: Code
+FIFO: MessageType
+FILTER_TYPE_UNSPECIFIED: FilterType
+FORBIDDEN: Code
+GOLANG: Language
+GZIP: Encoding
+HA_NOT_AVAILABLE: Code
+IDENTITY: Encoding
+ILLEGAL_ACCESS_POINT: Code
+ILLEGAL_CONSUMER_GROUP: Code
+ILLEGAL_DELIVERY_TIME: Code
+ILLEGAL_FILTER_EXPRESSION: Code
+ILLEGAL_INVISIBLE_TIME: Code
+ILLEGAL_MESSAGE_GROUP: Code
+ILLEGAL_MESSAGE_ID: Code
+ILLEGAL_MESSAGE_KEY: Code
+ILLEGAL_MESSAGE_PROPERTY_KEY: Code
+ILLEGAL_MESSAGE_TAG: Code
+ILLEGAL_POLLING_TIME: Code
+ILLEGAL_TOPIC: Code
+INTERNAL_ERROR: Code
+INTERNAL_SERVER_ERROR: Code
+INVALID_RECEIPT_HANDLE: Code
+INVALID_TRANSACTION_ID: Code
+IPv4: AddressScheme
+IPv6: AddressScheme
+JAVA: Language
+KOTLIN: Language
+LANGUAGE_UNSPECIFIED: Language
+MASTER_PERSISTENCE_TIMEOUT: Code
+MD5: DigestType
+MESSAGE_BODY_TOO_LARGE: Code
+MESSAGE_CORRUPTED: Code
+MESSAGE_NOT_FOUND: Code
+MESSAGE_PROPERTIES_TOO_LARGE: Code
+MESSAGE_PROPERTY_CONFLICT_WITH_TYPE: Code
+MESSAGE_TYPE_UNSPECIFIED: MessageType
+MULTIPLE_RESULTS: Code
+NODE_JS: Language
+NONE: Permission
+NORMAL: MessageType
+NOT_FOUND: Code
+NOT_IMPLEMENTED: Code
+OBJECTIVE_C: Language
+OK: Code
+PAYLOAD_TOO_LARGE: Code
+PAYMENT_REQUIRED: Code
+PERMISSION_UNSPECIFIED: Permission
+PHP: Language
+PRECONDITION_FAILED: Code
+PRODUCER: ClientType
+PROXY_TIMEOUT: Code
+PUSH_CONSUMER: ClientType
+PYTHON: Language
+READ: Permission
+READ_WRITE: Permission
+REQUEST_HEADER_FIELDS_TOO_LARGE: Code
+REQUEST_TIMEOUT: Code
+ROLLBACK: TransactionResolution
+RUBY: Language
+RUST: Language
+SHA1: DigestType
+SIMPLE_CONSUMER: ClientType
+SLAVE_PERSISTENCE_TIMEOUT: Code
+SOURCE_CLIENT: TransactionSource
+SOURCE_SERVER_CHECK: TransactionSource
+SOURCE_UNSPECIFIED: TransactionSource
+SQL: FilterType
+TAG: FilterType
+TOO_MANY_REQUESTS: Code
+TOPIC_NOT_FOUND: Code
+TRANSACTION: MessageType
+TRANSACTION_RESOLUTION_UNSPECIFIED: TransactionResolution
+UNAUTHORIZED: Code
+UNRECOGNIZED_CLIENT_TYPE: Code
+UNSUPPORTED: Code
+VERIFY_FIFO_MESSAGE_UNSUPPORTED: Code
+VERSION_UNSUPPORTED: Code
+WRITE: Permission
+
+class Address(_message.Message):
+    __slots__ = ["host", "port"]
+    HOST_FIELD_NUMBER: _ClassVar[int]
+    PORT_FIELD_NUMBER: _ClassVar[int]
+    host: str
+    port: int
+    def __init__(self, host: _Optional[str] = ..., port: _Optional[int] = ...) 
-> None: ...
+
+class Assignment(_message.Message):
+    __slots__ = ["message_queue"]
+    MESSAGE_QUEUE_FIELD_NUMBER: _ClassVar[int]
+    message_queue: MessageQueue
+    def __init__(self, message_queue: _Optional[_Union[MessageQueue, 
_Mapping]] = ...) -> None: ...
+
+class Broker(_message.Message):
+    __slots__ = ["endpoints", "id", "name"]
+    ENDPOINTS_FIELD_NUMBER: _ClassVar[int]
+    ID_FIELD_NUMBER: _ClassVar[int]
+    NAME_FIELD_NUMBER: _ClassVar[int]
+    endpoints: Endpoints
+    id: int
+    name: str
+    def __init__(self, name: _Optional[str] = ..., id: _Optional[int] = ..., 
endpoints: _Optional[_Union[Endpoints, _Mapping]] = ...) -> None: ...
+
+class CustomizedBackoff(_message.Message):
+    __slots__ = ["next"]
+    NEXT_FIELD_NUMBER: _ClassVar[int]
+    next: _containers.RepeatedCompositeFieldContainer[_duration_pb2.Duration]
+    def __init__(self, next: 
_Optional[_Iterable[_Union[_duration_pb2.Duration, _Mapping]]] = ...) -> None: 
...
+
+class DeadLetterQueue(_message.Message):
+    __slots__ = ["message_id", "topic"]
+    MESSAGE_ID_FIELD_NUMBER: _ClassVar[int]
+    TOPIC_FIELD_NUMBER: _ClassVar[int]
+    message_id: str
+    topic: str
+    def __init__(self, topic: _Optional[str] = ..., message_id: _Optional[str] 
= ...) -> None: ...
+
+class Digest(_message.Message):
+    __slots__ = ["checksum", "type"]
+    CHECKSUM_FIELD_NUMBER: _ClassVar[int]
+    TYPE_FIELD_NUMBER: _ClassVar[int]
+    checksum: str
+    type: DigestType
+    def __init__(self, type: _Optional[_Union[DigestType, str]] = ..., 
checksum: _Optional[str] = ...) -> None: ...
+
+class Endpoints(_message.Message):
+    __slots__ = ["addresses", "scheme"]
+    ADDRESSES_FIELD_NUMBER: _ClassVar[int]
+    SCHEME_FIELD_NUMBER: _ClassVar[int]
+    addresses: _containers.RepeatedCompositeFieldContainer[Address]
+    scheme: AddressScheme
+    def __init__(self, scheme: _Optional[_Union[AddressScheme, str]] = ..., 
addresses: _Optional[_Iterable[_Union[Address, _Mapping]]] = ...) -> None: ...
+
+class ExponentialBackoff(_message.Message):
+    __slots__ = ["initial", "max", "multiplier"]
+    INITIAL_FIELD_NUMBER: _ClassVar[int]
+    MAX_FIELD_NUMBER: _ClassVar[int]
+    MULTIPLIER_FIELD_NUMBER: _ClassVar[int]
+    initial: _duration_pb2.Duration
+    max: _duration_pb2.Duration
+    multiplier: float
+    def __init__(self, initial: _Optional[_Union[_duration_pb2.Duration, 
_Mapping]] = ..., max: _Optional[_Union[_duration_pb2.Duration, _Mapping]] = 
..., multiplier: _Optional[float] = ...) -> None: ...
+
+class FilterExpression(_message.Message):
+    __slots__ = ["expression", "type"]
+    EXPRESSION_FIELD_NUMBER: _ClassVar[int]
+    TYPE_FIELD_NUMBER: _ClassVar[int]
+    expression: str
+    type: FilterType
+    def __init__(self, type: _Optional[_Union[FilterType, str]] = ..., 
expression: _Optional[str] = ...) -> None: ...
+
+class Message(_message.Message):
+    __slots__ = ["body", "system_properties", "topic", "user_properties"]
+    class UserPropertiesEntry(_message.Message):
+        __slots__ = ["key", "value"]
+        KEY_FIELD_NUMBER: _ClassVar[int]
+        VALUE_FIELD_NUMBER: _ClassVar[int]
+        key: str
+        value: str
+        def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = 
...) -> None: ...
+    BODY_FIELD_NUMBER: _ClassVar[int]
+    SYSTEM_PROPERTIES_FIELD_NUMBER: _ClassVar[int]
+    TOPIC_FIELD_NUMBER: _ClassVar[int]
+    USER_PROPERTIES_FIELD_NUMBER: _ClassVar[int]
+    body: bytes
+    system_properties: SystemProperties
+    topic: Resource
+    user_properties: _containers.ScalarMap[str, str]
+    def __init__(self, topic: _Optional[_Union[Resource, _Mapping]] = ..., 
user_properties: _Optional[_Mapping[str, str]] = ..., system_properties: 
_Optional[_Union[SystemProperties, _Mapping]] = ..., body: _Optional[bytes] = 
...) -> None: ...
+
+class MessageQueue(_message.Message):
+    __slots__ = ["accept_message_types", "broker", "id", "permission", "topic"]
+    ACCEPT_MESSAGE_TYPES_FIELD_NUMBER: _ClassVar[int]
+    BROKER_FIELD_NUMBER: _ClassVar[int]
+    ID_FIELD_NUMBER: _ClassVar[int]
+    PERMISSION_FIELD_NUMBER: _ClassVar[int]
+    TOPIC_FIELD_NUMBER: _ClassVar[int]
+    accept_message_types: _containers.RepeatedScalarFieldContainer[MessageType]
+    broker: Broker
+    id: int
+    permission: Permission
+    topic: Resource
+    def __init__(self, topic: _Optional[_Union[Resource, _Mapping]] = ..., id: 
_Optional[int] = ..., permission: _Optional[_Union[Permission, str]] = ..., 
broker: _Optional[_Union[Broker, _Mapping]] = ..., accept_message_types: 
_Optional[_Iterable[_Union[MessageType, str]]] = ...) -> None: ...
+
+class Metric(_message.Message):
+    __slots__ = ["endpoints", "on"]
+    ENDPOINTS_FIELD_NUMBER: _ClassVar[int]
+    ON_FIELD_NUMBER: _ClassVar[int]
+    endpoints: Endpoints
+    on: bool
+    def __init__(self, on: bool = ..., endpoints: _Optional[_Union[Endpoints, 
_Mapping]] = ...) -> None: ...
+
+class Publishing(_message.Message):
+    __slots__ = ["max_body_size", "topics", "validate_message_type"]
+    MAX_BODY_SIZE_FIELD_NUMBER: _ClassVar[int]
+    TOPICS_FIELD_NUMBER: _ClassVar[int]
+    VALIDATE_MESSAGE_TYPE_FIELD_NUMBER: _ClassVar[int]
+    max_body_size: int
+    topics: _containers.RepeatedCompositeFieldContainer[Resource]
+    validate_message_type: bool
+    def __init__(self, topics: _Optional[_Iterable[_Union[Resource, 
_Mapping]]] = ..., max_body_size: _Optional[int] = ..., validate_message_type: 
bool = ...) -> None: ...
+
+class Resource(_message.Message):
+    __slots__ = ["name", "resource_namespace"]
+    NAME_FIELD_NUMBER: _ClassVar[int]
+    RESOURCE_NAMESPACE_FIELD_NUMBER: _ClassVar[int]
+    name: str
+    resource_namespace: str
+    def __init__(self, resource_namespace: _Optional[str] = ..., name: 
_Optional[str] = ...) -> None: ...
+
+class RetryPolicy(_message.Message):
+    __slots__ = ["customized_backoff", "exponential_backoff", "max_attempts"]
+    CUSTOMIZED_BACKOFF_FIELD_NUMBER: _ClassVar[int]
+    EXPONENTIAL_BACKOFF_FIELD_NUMBER: _ClassVar[int]
+    MAX_ATTEMPTS_FIELD_NUMBER: _ClassVar[int]
+    customized_backoff: CustomizedBackoff
+    exponential_backoff: ExponentialBackoff
+    max_attempts: int
+    def __init__(self, max_attempts: _Optional[int] = ..., 
exponential_backoff: _Optional[_Union[ExponentialBackoff, _Mapping]] = ..., 
customized_backoff: _Optional[_Union[CustomizedBackoff, _Mapping]] = ...) -> 
None: ...
+
+class Settings(_message.Message):
+    __slots__ = ["access_point", "backoff_policy", "client_type", "metric", 
"publishing", "request_timeout", "subscription", "user_agent"]
+    ACCESS_POINT_FIELD_NUMBER: _ClassVar[int]
+    BACKOFF_POLICY_FIELD_NUMBER: _ClassVar[int]
+    CLIENT_TYPE_FIELD_NUMBER: _ClassVar[int]
+    METRIC_FIELD_NUMBER: _ClassVar[int]
+    PUBLISHING_FIELD_NUMBER: _ClassVar[int]
+    REQUEST_TIMEOUT_FIELD_NUMBER: _ClassVar[int]
+    SUBSCRIPTION_FIELD_NUMBER: _ClassVar[int]
+    USER_AGENT_FIELD_NUMBER: _ClassVar[int]
+    access_point: Endpoints
+    backoff_policy: RetryPolicy
+    client_type: ClientType
+    metric: Metric
+    publishing: Publishing
+    request_timeout: _duration_pb2.Duration
+    subscription: Subscription
+    user_agent: UA
+    def __init__(self, client_type: _Optional[_Union[ClientType, str]] = ..., 
access_point: _Optional[_Union[Endpoints, _Mapping]] = ..., backoff_policy: 
_Optional[_Union[RetryPolicy, _Mapping]] = ..., request_timeout: 
_Optional[_Union[_duration_pb2.Duration, _Mapping]] = ..., publishing: 
_Optional[_Union[Publishing, _Mapping]] = ..., subscription: 
_Optional[_Union[Subscription, _Mapping]] = ..., user_agent: 
_Optional[_Union[UA, _Mapping]] = ..., metric: _Optional[_Union[Metric, 
_Mapping [...]
+
+class Status(_message.Message):
+    __slots__ = ["code", "message"]
+    CODE_FIELD_NUMBER: _ClassVar[int]
+    MESSAGE_FIELD_NUMBER: _ClassVar[int]
+    code: Code
+    message: str
+    def __init__(self, code: _Optional[_Union[Code, str]] = ..., message: 
_Optional[str] = ...) -> None: ...
+
+class Subscription(_message.Message):
+    __slots__ = ["fifo", "group", "long_polling_timeout", 
"receive_batch_size", "subscriptions"]
+    FIFO_FIELD_NUMBER: _ClassVar[int]
+    GROUP_FIELD_NUMBER: _ClassVar[int]
+    LONG_POLLING_TIMEOUT_FIELD_NUMBER: _ClassVar[int]
+    RECEIVE_BATCH_SIZE_FIELD_NUMBER: _ClassVar[int]
+    SUBSCRIPTIONS_FIELD_NUMBER: _ClassVar[int]
+    fifo: bool
+    group: Resource
+    long_polling_timeout: _duration_pb2.Duration
+    receive_batch_size: int
+    subscriptions: 
_containers.RepeatedCompositeFieldContainer[SubscriptionEntry]
+    def __init__(self, group: _Optional[_Union[Resource, _Mapping]] = ..., 
subscriptions: _Optional[_Iterable[_Union[SubscriptionEntry, _Mapping]]] = ..., 
fifo: bool = ..., receive_batch_size: _Optional[int] = ..., 
long_polling_timeout: _Optional[_Union[_duration_pb2.Duration, _Mapping]] = 
...) -> None: ...
+
+class SubscriptionEntry(_message.Message):
+    __slots__ = ["expression", "topic"]
+    EXPRESSION_FIELD_NUMBER: _ClassVar[int]
+    TOPIC_FIELD_NUMBER: _ClassVar[int]
+    expression: FilterExpression
+    topic: Resource
+    def __init__(self, topic: _Optional[_Union[Resource, _Mapping]] = ..., 
expression: _Optional[_Union[FilterExpression, _Mapping]] = ...) -> None: ...
+
+class SystemProperties(_message.Message):
+    __slots__ = ["body_digest", "body_encoding", "born_host", 
"born_timestamp", "dead_letter_queue", "delivery_attempt", 
"delivery_timestamp", "invisible_duration", "keys", "message_group", 
"message_id", "message_type", "orphaned_transaction_recovery_duration", 
"queue_id", "queue_offset", "receipt_handle", "store_host", "store_timestamp", 
"tag", "trace_context"]
+    BODY_DIGEST_FIELD_NUMBER: _ClassVar[int]
+    BODY_ENCODING_FIELD_NUMBER: _ClassVar[int]
+    BORN_HOST_FIELD_NUMBER: _ClassVar[int]
+    BORN_TIMESTAMP_FIELD_NUMBER: _ClassVar[int]
+    DEAD_LETTER_QUEUE_FIELD_NUMBER: _ClassVar[int]
+    DELIVERY_ATTEMPT_FIELD_NUMBER: _ClassVar[int]
+    DELIVERY_TIMESTAMP_FIELD_NUMBER: _ClassVar[int]
+    INVISIBLE_DURATION_FIELD_NUMBER: _ClassVar[int]
+    KEYS_FIELD_NUMBER: _ClassVar[int]
+    MESSAGE_GROUP_FIELD_NUMBER: _ClassVar[int]
+    MESSAGE_ID_FIELD_NUMBER: _ClassVar[int]
+    MESSAGE_TYPE_FIELD_NUMBER: _ClassVar[int]
+    ORPHANED_TRANSACTION_RECOVERY_DURATION_FIELD_NUMBER: _ClassVar[int]
+    QUEUE_ID_FIELD_NUMBER: _ClassVar[int]
+    QUEUE_OFFSET_FIELD_NUMBER: _ClassVar[int]
+    RECEIPT_HANDLE_FIELD_NUMBER: _ClassVar[int]
+    STORE_HOST_FIELD_NUMBER: _ClassVar[int]
+    STORE_TIMESTAMP_FIELD_NUMBER: _ClassVar[int]
+    TAG_FIELD_NUMBER: _ClassVar[int]
+    TRACE_CONTEXT_FIELD_NUMBER: _ClassVar[int]
+    body_digest: Digest
+    body_encoding: Encoding
+    born_host: str
+    born_timestamp: _timestamp_pb2.Timestamp
+    dead_letter_queue: DeadLetterQueue
+    delivery_attempt: int
+    delivery_timestamp: _timestamp_pb2.Timestamp
+    invisible_duration: _duration_pb2.Duration
+    keys: _containers.RepeatedScalarFieldContainer[str]
+    message_group: str
+    message_id: str
+    message_type: MessageType
+    orphaned_transaction_recovery_duration: _duration_pb2.Duration
+    queue_id: int
+    queue_offset: int
+    receipt_handle: str
+    store_host: str
+    store_timestamp: _timestamp_pb2.Timestamp
+    tag: str
+    trace_context: str
+    def __init__(self, tag: _Optional[str] = ..., keys: 
_Optional[_Iterable[str]] = ..., message_id: _Optional[str] = ..., body_digest: 
_Optional[_Union[Digest, _Mapping]] = ..., body_encoding: 
_Optional[_Union[Encoding, str]] = ..., message_type: 
_Optional[_Union[MessageType, str]] = ..., born_timestamp: 
_Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., born_host: 
_Optional[str] = ..., store_timestamp: 
_Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., store_host: _ [...]
+
+class UA(_message.Message):
+    __slots__ = ["hostname", "language", "platform", "version"]
+    HOSTNAME_FIELD_NUMBER: _ClassVar[int]
+    LANGUAGE_FIELD_NUMBER: _ClassVar[int]
+    PLATFORM_FIELD_NUMBER: _ClassVar[int]
+    VERSION_FIELD_NUMBER: _ClassVar[int]
+    hostname: str
+    language: Language
+    platform: str
+    version: str
+    def __init__(self, language: _Optional[_Union[Language, str]] = ..., 
version: _Optional[str] = ..., platform: _Optional[str] = ..., hostname: 
_Optional[str] = ...) -> None: ...
+
+class TransactionResolution(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+    __slots__ = []
+
+class TransactionSource(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+    __slots__ = []
+
+class Permission(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+    __slots__ = []
+
+class FilterType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+    __slots__ = []
+
+class AddressScheme(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+    __slots__ = []
+
+class MessageType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+    __slots__ = []
+
+class DigestType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+    __slots__ = []
+
+class ClientType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+    __slots__ = []
+
+class Encoding(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+    __slots__ = []
+
+class Code(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+    __slots__ = []
+
+class Language(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+    __slots__ = []
diff --git a/python/protocol/definition_pb2_grpc.py 
b/python/rocketmq/protocol/definition_pb2_grpc.py
similarity index 99%
copy from python/protocol/definition_pb2_grpc.py
copy to python/rocketmq/protocol/definition_pb2_grpc.py
index 2cd6c817..03079090 100644
--- a/python/protocol/definition_pb2_grpc.py
+++ b/python/rocketmq/protocol/definition_pb2_grpc.py
@@ -4,9 +4,9 @@
 # The ASF licenses this file to You under the Apache License, Version 2.0
 # (the "License"); you may not use this file except in compliance with
 # the License.  You may obtain a copy of the License at
-# 
+#
 #     http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
diff --git a/python/rocketmq/protocol/service_pb2.py 
b/python/rocketmq/protocol/service_pb2.py
new file mode 100644
index 00000000..2b4ec62d
--- /dev/null
+++ b/python/rocketmq/protocol/service_pb2.py
@@ -0,0 +1,102 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: apache/rocketmq/v2/service.proto
+"""Generated protocol buffer code."""
+from google.protobuf.internal import builder as _builder
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+from google.protobuf import duration_pb2 as 
google_dot_protobuf_dot_duration__pb2
+from google.protobuf import timestamp_pb2 as 
google_dot_protobuf_dot_timestamp__pb2
+from protocol import definition_pb2 as 
apache_dot_rocketmq_dot_v2_dot_definition__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n 
apache/rocketmq/v2/service.proto\x12\x12\x61pache.rocketmq.v2\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a#apache/rocketmq/v2/definition.proto\"r\n\x11QueryRouteRequest\x12+\n\x05topic\x18\x01
 \x01(\x0b\x32\x1c.apache.rocketmq.v2.Resource\x12\x30\n\tendpoints\x18\x02 
\x01(\x0b\x32\x1d.apache.rocketmq.v2.Endpoints\"z\n\x12QueryRouteResponse\x12*\n\x06status\x18\x01
 \x01(\x0b\x32\x1a.apache.r [...]
+
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 
'apache.rocketmq.v2.service_pb2', globals())
+if _descriptor._USE_C_DESCRIPTORS == False:
+
+  DESCRIPTOR._options = None
+  DESCRIPTOR._serialized_options = 
b'\n\022apache.rocketmq.v2B\tMQServiceP\001\240\001\001\330\001\001\252\002\022Apache.Rocketmq.V2'
+  _QUERYROUTEREQUEST._serialized_start=158
+  _QUERYROUTEREQUEST._serialized_end=272
+  _QUERYROUTERESPONSE._serialized_start=274
+  _QUERYROUTERESPONSE._serialized_end=396
+  _SENDMESSAGEREQUEST._serialized_start=398
+  _SENDMESSAGEREQUEST._serialized_end=465
+  _SENDRESULTENTRY._serialized_start=467
+  _SENDRESULTENTRY._serialized_end=588
+  _SENDMESSAGERESPONSE._serialized_start=590
+  _SENDMESSAGERESPONSE._serialized_end=709
+  _QUERYASSIGNMENTREQUEST._serialized_start=712
+  _QUERYASSIGNMENTREQUEST._serialized_end=876
+  _QUERYASSIGNMENTRESPONSE._serialized_start=878
+  _QUERYASSIGNMENTRESPONSE._serialized_end=1000
+  _RECEIVEMESSAGEREQUEST._serialized_start=1003
+  _RECEIVEMESSAGEREQUEST._serialized_end=1403
+  _RECEIVEMESSAGERESPONSE._serialized_start=1406
+  _RECEIVEMESSAGERESPONSE._serialized_end=1593
+  _ACKMESSAGEENTRY._serialized_start=1595
+  _ACKMESSAGEENTRY._serialized_end=1656
+  _ACKMESSAGEREQUEST._serialized_start=1659
+  _ACKMESSAGEREQUEST._serialized_end=1822
+  _ACKMESSAGERESULTENTRY._serialized_start=1824
+  _ACKMESSAGERESULTENTRY._serialized_end=1935
+  _ACKMESSAGERESPONSE._serialized_start=1937
+  _ACKMESSAGERESPONSE._serialized_end=2061
+  _FORWARDMESSAGETODEADLETTERQUEUEREQUEST._serialized_start=2064
+  _FORWARDMESSAGETODEADLETTERQUEUEREQUEST._serialized_end=2295
+  _FORWARDMESSAGETODEADLETTERQUEUERESPONSE._serialized_start=2297
+  _FORWARDMESSAGETODEADLETTERQUEUERESPONSE._serialized_end=2382
+  _HEARTBEATREQUEST._serialized_start=2385
+  _HEARTBEATREQUEST._serialized_end=2516
+  _HEARTBEATRESPONSE._serialized_start=2518
+  _HEARTBEATRESPONSE._serialized_end=2581
+  _ENDTRANSACTIONREQUEST._serialized_start=2584
+  _ENDTRANSACTIONREQUEST._serialized_end=2837
+  _ENDTRANSACTIONRESPONSE._serialized_start=2839
+  _ENDTRANSACTIONRESPONSE._serialized_end=2907
+  _PRINTTHREADSTACKTRACECOMMAND._serialized_start=2909
+  _PRINTTHREADSTACKTRACECOMMAND._serialized_end=2954
+  _THREADSTACKTRACE._serialized_start=2956
+  _THREADSTACKTRACE._serialized_end=3045
+  _VERIFYMESSAGECOMMAND._serialized_start=3047
+  _VERIFYMESSAGECOMMAND._serialized_end=3130
+  _VERIFYMESSAGERESULT._serialized_start=3132
+  _VERIFYMESSAGERESULT._serialized_end=3168
+  _RECOVERORPHANEDTRANSACTIONCOMMAND._serialized_start=3170
+  _RECOVERORPHANEDTRANSACTIONCOMMAND._serialized_end=3275
+  _TELEMETRYCOMMAND._serialized_start=3278
+  _TELEMETRYCOMMAND._serialized_end=3832
+  _NOTIFYCLIENTTERMINATIONREQUEST._serialized_start=3834
+  _NOTIFYCLIENTTERMINATIONREQUEST._serialized_end=3926
+  _NOTIFYCLIENTTERMINATIONRESPONSE._serialized_start=3928
+  _NOTIFYCLIENTTERMINATIONRESPONSE._serialized_end=4005
+  _CHANGEINVISIBLEDURATIONREQUEST._serialized_start=4008
+  _CHANGEINVISIBLEDURATIONREQUEST._serialized_end=4229
+  _CHANGEINVISIBLEDURATIONRESPONSE._serialized_start=4231
+  _CHANGEINVISIBLEDURATIONRESPONSE._serialized_end=4332
+  _MESSAGINGSERVICE._serialized_start=4335
+  _MESSAGINGSERVICE._serialized_end=5583
+# @@protoc_insertion_point(module_scope)
diff --git a/python/rocketmq/protocol/service_pb2.pyi 
b/python/rocketmq/protocol/service_pb2.pyi
new file mode 100644
index 00000000..7418dcb0
--- /dev/null
+++ b/python/rocketmq/protocol/service_pb2.pyi
@@ -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.
+
+from google.protobuf import duration_pb2 as _duration_pb2
+from google.protobuf import timestamp_pb2 as _timestamp_pb2
+from protocol import definition_pb2 as _definition_pb2
+from google.protobuf.internal import containers as _containers
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as 
_Mapping, Optional as _Optional, Union as _Union
+
+DESCRIPTOR: _descriptor.FileDescriptor
+
+class AckMessageEntry(_message.Message):
+    __slots__ = ["message_id", "receipt_handle"]
+    MESSAGE_ID_FIELD_NUMBER: _ClassVar[int]
+    RECEIPT_HANDLE_FIELD_NUMBER: _ClassVar[int]
+    message_id: str
+    receipt_handle: str
+    def __init__(self, message_id: _Optional[str] = ..., receipt_handle: 
_Optional[str] = ...) -> None: ...
+
+class AckMessageRequest(_message.Message):
+    __slots__ = ["entries", "group", "topic"]
+    ENTRIES_FIELD_NUMBER: _ClassVar[int]
+    GROUP_FIELD_NUMBER: _ClassVar[int]
+    TOPIC_FIELD_NUMBER: _ClassVar[int]
+    entries: _containers.RepeatedCompositeFieldContainer[AckMessageEntry]
+    group: _definition_pb2.Resource
+    topic: _definition_pb2.Resource
+    def __init__(self, group: _Optional[_Union[_definition_pb2.Resource, 
_Mapping]] = ..., topic: _Optional[_Union[_definition_pb2.Resource, _Mapping]] 
= ..., entries: _Optional[_Iterable[_Union[AckMessageEntry, _Mapping]]] = ...) 
-> None: ...
+
+class AckMessageResponse(_message.Message):
+    __slots__ = ["entries", "status"]
+    ENTRIES_FIELD_NUMBER: _ClassVar[int]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    entries: _containers.RepeatedCompositeFieldContainer[AckMessageResultEntry]
+    status: _definition_pb2.Status
+    def __init__(self, status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ..., entries: _Optional[_Iterable[_Union[AckMessageResultEntry, 
_Mapping]]] = ...) -> None: ...
+
+class AckMessageResultEntry(_message.Message):
+    __slots__ = ["message_id", "receipt_handle", "status"]
+    MESSAGE_ID_FIELD_NUMBER: _ClassVar[int]
+    RECEIPT_HANDLE_FIELD_NUMBER: _ClassVar[int]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    message_id: str
+    receipt_handle: str
+    status: _definition_pb2.Status
+    def __init__(self, message_id: _Optional[str] = ..., receipt_handle: 
_Optional[str] = ..., status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ...) -> None: ...
+
+class ChangeInvisibleDurationRequest(_message.Message):
+    __slots__ = ["group", "invisible_duration", "message_id", 
"receipt_handle", "topic"]
+    GROUP_FIELD_NUMBER: _ClassVar[int]
+    INVISIBLE_DURATION_FIELD_NUMBER: _ClassVar[int]
+    MESSAGE_ID_FIELD_NUMBER: _ClassVar[int]
+    RECEIPT_HANDLE_FIELD_NUMBER: _ClassVar[int]
+    TOPIC_FIELD_NUMBER: _ClassVar[int]
+    group: _definition_pb2.Resource
+    invisible_duration: _duration_pb2.Duration
+    message_id: str
+    receipt_handle: str
+    topic: _definition_pb2.Resource
+    def __init__(self, group: _Optional[_Union[_definition_pb2.Resource, 
_Mapping]] = ..., topic: _Optional[_Union[_definition_pb2.Resource, _Mapping]] 
= ..., receipt_handle: _Optional[str] = ..., invisible_duration: 
_Optional[_Union[_duration_pb2.Duration, _Mapping]] = ..., message_id: 
_Optional[str] = ...) -> None: ...
+
+class ChangeInvisibleDurationResponse(_message.Message):
+    __slots__ = ["receipt_handle", "status"]
+    RECEIPT_HANDLE_FIELD_NUMBER: _ClassVar[int]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    receipt_handle: str
+    status: _definition_pb2.Status
+    def __init__(self, status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ..., receipt_handle: _Optional[str] = ...) -> None: ...
+
+class EndTransactionRequest(_message.Message):
+    __slots__ = ["message_id", "resolution", "source", "topic", 
"trace_context", "transaction_id"]
+    MESSAGE_ID_FIELD_NUMBER: _ClassVar[int]
+    RESOLUTION_FIELD_NUMBER: _ClassVar[int]
+    SOURCE_FIELD_NUMBER: _ClassVar[int]
+    TOPIC_FIELD_NUMBER: _ClassVar[int]
+    TRACE_CONTEXT_FIELD_NUMBER: _ClassVar[int]
+    TRANSACTION_ID_FIELD_NUMBER: _ClassVar[int]
+    message_id: str
+    resolution: _definition_pb2.TransactionResolution
+    source: _definition_pb2.TransactionSource
+    topic: _definition_pb2.Resource
+    trace_context: str
+    transaction_id: str
+    def __init__(self, topic: _Optional[_Union[_definition_pb2.Resource, 
_Mapping]] = ..., message_id: _Optional[str] = ..., transaction_id: 
_Optional[str] = ..., resolution: 
_Optional[_Union[_definition_pb2.TransactionResolution, str]] = ..., source: 
_Optional[_Union[_definition_pb2.TransactionSource, str]] = ..., trace_context: 
_Optional[str] = ...) -> None: ...
+
+class EndTransactionResponse(_message.Message):
+    __slots__ = ["status"]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    status: _definition_pb2.Status
+    def __init__(self, status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ...) -> None: ...
+
+class ForwardMessageToDeadLetterQueueRequest(_message.Message):
+    __slots__ = ["delivery_attempt", "group", "max_delivery_attempts", 
"message_id", "receipt_handle", "topic"]
+    DELIVERY_ATTEMPT_FIELD_NUMBER: _ClassVar[int]
+    GROUP_FIELD_NUMBER: _ClassVar[int]
+    MAX_DELIVERY_ATTEMPTS_FIELD_NUMBER: _ClassVar[int]
+    MESSAGE_ID_FIELD_NUMBER: _ClassVar[int]
+    RECEIPT_HANDLE_FIELD_NUMBER: _ClassVar[int]
+    TOPIC_FIELD_NUMBER: _ClassVar[int]
+    delivery_attempt: int
+    group: _definition_pb2.Resource
+    max_delivery_attempts: int
+    message_id: str
+    receipt_handle: str
+    topic: _definition_pb2.Resource
+    def __init__(self, group: _Optional[_Union[_definition_pb2.Resource, 
_Mapping]] = ..., topic: _Optional[_Union[_definition_pb2.Resource, _Mapping]] 
= ..., receipt_handle: _Optional[str] = ..., message_id: _Optional[str] = ..., 
delivery_attempt: _Optional[int] = ..., max_delivery_attempts: _Optional[int] = 
...) -> None: ...
+
+class ForwardMessageToDeadLetterQueueResponse(_message.Message):
+    __slots__ = ["status"]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    status: _definition_pb2.Status
+    def __init__(self, status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ...) -> None: ...
+
+class HeartbeatRequest(_message.Message):
+    __slots__ = ["client_type", "group"]
+    CLIENT_TYPE_FIELD_NUMBER: _ClassVar[int]
+    GROUP_FIELD_NUMBER: _ClassVar[int]
+    client_type: _definition_pb2.ClientType
+    group: _definition_pb2.Resource
+    def __init__(self, group: _Optional[_Union[_definition_pb2.Resource, 
_Mapping]] = ..., client_type: _Optional[_Union[_definition_pb2.ClientType, 
str]] = ...) -> None: ...
+
+class HeartbeatResponse(_message.Message):
+    __slots__ = ["status"]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    status: _definition_pb2.Status
+    def __init__(self, status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ...) -> None: ...
+
+class NotifyClientTerminationRequest(_message.Message):
+    __slots__ = ["group"]
+    GROUP_FIELD_NUMBER: _ClassVar[int]
+    group: _definition_pb2.Resource
+    def __init__(self, group: _Optional[_Union[_definition_pb2.Resource, 
_Mapping]] = ...) -> None: ...
+
+class NotifyClientTerminationResponse(_message.Message):
+    __slots__ = ["status"]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    status: _definition_pb2.Status
+    def __init__(self, status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ...) -> None: ...
+
+class PrintThreadStackTraceCommand(_message.Message):
+    __slots__ = ["nonce"]
+    NONCE_FIELD_NUMBER: _ClassVar[int]
+    nonce: str
+    def __init__(self, nonce: _Optional[str] = ...) -> None: ...
+
+class QueryAssignmentRequest(_message.Message):
+    __slots__ = ["endpoints", "group", "topic"]
+    ENDPOINTS_FIELD_NUMBER: _ClassVar[int]
+    GROUP_FIELD_NUMBER: _ClassVar[int]
+    TOPIC_FIELD_NUMBER: _ClassVar[int]
+    endpoints: _definition_pb2.Endpoints
+    group: _definition_pb2.Resource
+    topic: _definition_pb2.Resource
+    def __init__(self, topic: _Optional[_Union[_definition_pb2.Resource, 
_Mapping]] = ..., group: _Optional[_Union[_definition_pb2.Resource, _Mapping]] 
= ..., endpoints: _Optional[_Union[_definition_pb2.Endpoints, _Mapping]] = ...) 
-> None: ...
+
+class QueryAssignmentResponse(_message.Message):
+    __slots__ = ["assignments", "status"]
+    ASSIGNMENTS_FIELD_NUMBER: _ClassVar[int]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    assignments: 
_containers.RepeatedCompositeFieldContainer[_definition_pb2.Assignment]
+    status: _definition_pb2.Status
+    def __init__(self, status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ..., assignments: 
_Optional[_Iterable[_Union[_definition_pb2.Assignment, _Mapping]]] = ...) -> 
None: ...
+
+class QueryRouteRequest(_message.Message):
+    __slots__ = ["endpoints", "topic"]
+    ENDPOINTS_FIELD_NUMBER: _ClassVar[int]
+    TOPIC_FIELD_NUMBER: _ClassVar[int]
+    endpoints: _definition_pb2.Endpoints
+    topic: _definition_pb2.Resource
+    def __init__(self, topic: _Optional[_Union[_definition_pb2.Resource, 
_Mapping]] = ..., endpoints: _Optional[_Union[_definition_pb2.Endpoints, 
_Mapping]] = ...) -> None: ...
+
+class QueryRouteResponse(_message.Message):
+    __slots__ = ["message_queues", "status"]
+    MESSAGE_QUEUES_FIELD_NUMBER: _ClassVar[int]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    message_queues: 
_containers.RepeatedCompositeFieldContainer[_definition_pb2.MessageQueue]
+    status: _definition_pb2.Status
+    def __init__(self, status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ..., message_queues: 
_Optional[_Iterable[_Union[_definition_pb2.MessageQueue, _Mapping]]] = ...) -> 
None: ...
+
+class ReceiveMessageRequest(_message.Message):
+    __slots__ = ["auto_renew", "batch_size", "filter_expression", "group", 
"invisible_duration", "long_polling_timeout", "message_queue"]
+    AUTO_RENEW_FIELD_NUMBER: _ClassVar[int]
+    BATCH_SIZE_FIELD_NUMBER: _ClassVar[int]
+    FILTER_EXPRESSION_FIELD_NUMBER: _ClassVar[int]
+    GROUP_FIELD_NUMBER: _ClassVar[int]
+    INVISIBLE_DURATION_FIELD_NUMBER: _ClassVar[int]
+    LONG_POLLING_TIMEOUT_FIELD_NUMBER: _ClassVar[int]
+    MESSAGE_QUEUE_FIELD_NUMBER: _ClassVar[int]
+    auto_renew: bool
+    batch_size: int
+    filter_expression: _definition_pb2.FilterExpression
+    group: _definition_pb2.Resource
+    invisible_duration: _duration_pb2.Duration
+    long_polling_timeout: _duration_pb2.Duration
+    message_queue: _definition_pb2.MessageQueue
+    def __init__(self, group: _Optional[_Union[_definition_pb2.Resource, 
_Mapping]] = ..., message_queue: _Optional[_Union[_definition_pb2.MessageQueue, 
_Mapping]] = ..., filter_expression: 
_Optional[_Union[_definition_pb2.FilterExpression, _Mapping]] = ..., 
batch_size: _Optional[int] = ..., invisible_duration: 
_Optional[_Union[_duration_pb2.Duration, _Mapping]] = ..., auto_renew: bool = 
..., long_polling_timeout: _Optional[_Union[_duration_pb2.Duration, _Mapping]] 
= ...) -> None: ...
+
+class ReceiveMessageResponse(_message.Message):
+    __slots__ = ["delivery_timestamp", "message", "status"]
+    DELIVERY_TIMESTAMP_FIELD_NUMBER: _ClassVar[int]
+    MESSAGE_FIELD_NUMBER: _ClassVar[int]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    delivery_timestamp: _timestamp_pb2.Timestamp
+    message: _definition_pb2.Message
+    status: _definition_pb2.Status
+    def __init__(self, status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ..., message: _Optional[_Union[_definition_pb2.Message, _Mapping]] 
= ..., delivery_timestamp: _Optional[_Union[_timestamp_pb2.Timestamp, 
_Mapping]] = ...) -> None: ...
+
+class RecoverOrphanedTransactionCommand(_message.Message):
+    __slots__ = ["message", "transaction_id"]
+    MESSAGE_FIELD_NUMBER: _ClassVar[int]
+    TRANSACTION_ID_FIELD_NUMBER: _ClassVar[int]
+    message: _definition_pb2.Message
+    transaction_id: str
+    def __init__(self, message: _Optional[_Union[_definition_pb2.Message, 
_Mapping]] = ..., transaction_id: _Optional[str] = ...) -> None: ...
+
+class SendMessageRequest(_message.Message):
+    __slots__ = ["messages"]
+    MESSAGES_FIELD_NUMBER: _ClassVar[int]
+    messages: 
_containers.RepeatedCompositeFieldContainer[_definition_pb2.Message]
+    def __init__(self, messages: 
_Optional[_Iterable[_Union[_definition_pb2.Message, _Mapping]]] = ...) -> None: 
...
+
+class SendMessageResponse(_message.Message):
+    __slots__ = ["entries", "status"]
+    ENTRIES_FIELD_NUMBER: _ClassVar[int]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    entries: _containers.RepeatedCompositeFieldContainer[SendResultEntry]
+    status: _definition_pb2.Status
+    def __init__(self, status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ..., entries: _Optional[_Iterable[_Union[SendResultEntry, 
_Mapping]]] = ...) -> None: ...
+
+class SendResultEntry(_message.Message):
+    __slots__ = ["message_id", "offset", "status", "transaction_id"]
+    MESSAGE_ID_FIELD_NUMBER: _ClassVar[int]
+    OFFSET_FIELD_NUMBER: _ClassVar[int]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    TRANSACTION_ID_FIELD_NUMBER: _ClassVar[int]
+    message_id: str
+    offset: int
+    status: _definition_pb2.Status
+    transaction_id: str
+    def __init__(self, status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ..., message_id: _Optional[str] = ..., transaction_id: 
_Optional[str] = ..., offset: _Optional[int] = ...) -> None: ...
+
+class TelemetryCommand(_message.Message):
+    __slots__ = ["print_thread_stack_trace_command", 
"recover_orphaned_transaction_command", "settings", "status", 
"thread_stack_trace", "verify_message_command", "verify_message_result"]
+    PRINT_THREAD_STACK_TRACE_COMMAND_FIELD_NUMBER: _ClassVar[int]
+    RECOVER_ORPHANED_TRANSACTION_COMMAND_FIELD_NUMBER: _ClassVar[int]
+    SETTINGS_FIELD_NUMBER: _ClassVar[int]
+    STATUS_FIELD_NUMBER: _ClassVar[int]
+    THREAD_STACK_TRACE_FIELD_NUMBER: _ClassVar[int]
+    VERIFY_MESSAGE_COMMAND_FIELD_NUMBER: _ClassVar[int]
+    VERIFY_MESSAGE_RESULT_FIELD_NUMBER: _ClassVar[int]
+    print_thread_stack_trace_command: PrintThreadStackTraceCommand
+    recover_orphaned_transaction_command: RecoverOrphanedTransactionCommand
+    settings: _definition_pb2.Settings
+    status: _definition_pb2.Status
+    thread_stack_trace: ThreadStackTrace
+    verify_message_command: VerifyMessageCommand
+    verify_message_result: VerifyMessageResult
+    def __init__(self, status: _Optional[_Union[_definition_pb2.Status, 
_Mapping]] = ..., settings: _Optional[_Union[_definition_pb2.Settings, 
_Mapping]] = ..., thread_stack_trace: _Optional[_Union[ThreadStackTrace, 
_Mapping]] = ..., verify_message_result: _Optional[_Union[VerifyMessageResult, 
_Mapping]] = ..., recover_orphaned_transaction_command: 
_Optional[_Union[RecoverOrphanedTransactionCommand, _Mapping]] = ..., 
print_thread_stack_trace_command: _Optional[_Union[PrintThreadStackTrac [...]
+
+class ThreadStackTrace(_message.Message):
+    __slots__ = ["nonce", "thread_stack_trace"]
+    NONCE_FIELD_NUMBER: _ClassVar[int]
+    THREAD_STACK_TRACE_FIELD_NUMBER: _ClassVar[int]
+    nonce: str
+    thread_stack_trace: str
+    def __init__(self, nonce: _Optional[str] = ..., thread_stack_trace: 
_Optional[str] = ...) -> None: ...
+
+class VerifyMessageCommand(_message.Message):
+    __slots__ = ["message", "nonce"]
+    MESSAGE_FIELD_NUMBER: _ClassVar[int]
+    NONCE_FIELD_NUMBER: _ClassVar[int]
+    message: _definition_pb2.Message
+    nonce: str
+    def __init__(self, nonce: _Optional[str] = ..., message: 
_Optional[_Union[_definition_pb2.Message, _Mapping]] = ...) -> None: ...
+
+class VerifyMessageResult(_message.Message):
+    __slots__ = ["nonce"]
+    NONCE_FIELD_NUMBER: _ClassVar[int]
+    nonce: str
+    def __init__(self, nonce: _Optional[str] = ...) -> None: ...
diff --git a/python/protocol/service_pb2_grpc.py 
b/python/rocketmq/protocol/service_pb2_grpc.py
similarity index 71%
rename from python/protocol/service_pb2_grpc.py
rename to python/rocketmq/protocol/service_pb2_grpc.py
index bc7050c4..028aed49 100644
--- a/python/protocol/service_pb2_grpc.py
+++ b/python/rocketmq/protocol/service_pb2_grpc.py
@@ -4,9 +4,9 @@
 # The ASF licenses this file to You under the Apache License, Version 2.0
 # (the "License"); you may not use this file except in compliance with
 # the License.  You may obtain a copy of the License at
-# 
+#
 #     http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,7 +17,7 @@
 """Client and server classes corresponding to protobuf-defined services."""
 import grpc
 
-import service_pb2 as service__pb2
+from protocol import service_pb2 as apache_dot_rocketmq_dot_v2_dot_service__pb2
 
 
 class MessagingServiceStub(object):
@@ -41,58 +41,58 @@ class MessagingServiceStub(object):
         """
         self.QueryRoute = channel.unary_unary(
                 '/apache.rocketmq.v2.MessagingService/QueryRoute',
-                
request_serializer=service__pb2.QueryRouteRequest.SerializeToString,
-                
response_deserializer=service__pb2.QueryRouteResponse.FromString,
+                
request_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.QueryRouteRequest.SerializeToString,
+                
response_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.QueryRouteResponse.FromString,
                 )
         self.Heartbeat = channel.unary_unary(
                 '/apache.rocketmq.v2.MessagingService/Heartbeat',
-                
request_serializer=service__pb2.HeartbeatRequest.SerializeToString,
-                
response_deserializer=service__pb2.HeartbeatResponse.FromString,
+                
request_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.HeartbeatRequest.SerializeToString,
+                
response_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.HeartbeatResponse.FromString,
                 )
         self.SendMessage = channel.unary_unary(
                 '/apache.rocketmq.v2.MessagingService/SendMessage',
-                
request_serializer=service__pb2.SendMessageRequest.SerializeToString,
-                
response_deserializer=service__pb2.SendMessageResponse.FromString,
+                
request_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.SendMessageRequest.SerializeToString,
+                
response_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.SendMessageResponse.FromString,
                 )
         self.QueryAssignment = channel.unary_unary(
                 '/apache.rocketmq.v2.MessagingService/QueryAssignment',
-                
request_serializer=service__pb2.QueryAssignmentRequest.SerializeToString,
-                
response_deserializer=service__pb2.QueryAssignmentResponse.FromString,
+                
request_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.QueryAssignmentRequest.SerializeToString,
+                
response_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.QueryAssignmentResponse.FromString,
                 )
         self.ReceiveMessage = channel.unary_stream(
                 '/apache.rocketmq.v2.MessagingService/ReceiveMessage',
-                
request_serializer=service__pb2.ReceiveMessageRequest.SerializeToString,
-                
response_deserializer=service__pb2.ReceiveMessageResponse.FromString,
+                
request_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.ReceiveMessageRequest.SerializeToString,
+                
response_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.ReceiveMessageResponse.FromString,
                 )
         self.AckMessage = channel.unary_unary(
                 '/apache.rocketmq.v2.MessagingService/AckMessage',
-                
request_serializer=service__pb2.AckMessageRequest.SerializeToString,
-                
response_deserializer=service__pb2.AckMessageResponse.FromString,
+                
request_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.AckMessageRequest.SerializeToString,
+                
response_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.AckMessageResponse.FromString,
                 )
         self.ForwardMessageToDeadLetterQueue = channel.unary_unary(
                 
'/apache.rocketmq.v2.MessagingService/ForwardMessageToDeadLetterQueue',
-                
request_serializer=service__pb2.ForwardMessageToDeadLetterQueueRequest.SerializeToString,
-                
response_deserializer=service__pb2.ForwardMessageToDeadLetterQueueResponse.FromString,
+                
request_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.ForwardMessageToDeadLetterQueueRequest.SerializeToString,
+                
response_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.ForwardMessageToDeadLetterQueueResponse.FromString,
                 )
         self.EndTransaction = channel.unary_unary(
                 '/apache.rocketmq.v2.MessagingService/EndTransaction',
-                
request_serializer=service__pb2.EndTransactionRequest.SerializeToString,
-                
response_deserializer=service__pb2.EndTransactionResponse.FromString,
+                
request_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.EndTransactionRequest.SerializeToString,
+                
response_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.EndTransactionResponse.FromString,
                 )
         self.Telemetry = channel.stream_stream(
                 '/apache.rocketmq.v2.MessagingService/Telemetry',
-                
request_serializer=service__pb2.TelemetryCommand.SerializeToString,
-                response_deserializer=service__pb2.TelemetryCommand.FromString,
+                
request_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.TelemetryCommand.SerializeToString,
+                
response_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.TelemetryCommand.FromString,
                 )
         self.NotifyClientTermination = channel.unary_unary(
                 '/apache.rocketmq.v2.MessagingService/NotifyClientTermination',
-                
request_serializer=service__pb2.NotifyClientTerminationRequest.SerializeToString,
-                
response_deserializer=service__pb2.NotifyClientTerminationResponse.FromString,
+                
request_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.NotifyClientTerminationRequest.SerializeToString,
+                
response_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.NotifyClientTerminationResponse.FromString,
                 )
         self.ChangeInvisibleDuration = channel.unary_unary(
                 '/apache.rocketmq.v2.MessagingService/ChangeInvisibleDuration',
-                
request_serializer=service__pb2.ChangeInvisibleDurationRequest.SerializeToString,
-                
response_deserializer=service__pb2.ChangeInvisibleDurationResponse.FromString,
+                
request_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.ChangeInvisibleDurationRequest.SerializeToString,
+                
response_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.ChangeInvisibleDurationResponse.FromString,
                 )
 
 
@@ -250,58 +250,58 @@ def add_MessagingServiceServicer_to_server(servicer, 
server):
     rpc_method_handlers = {
             'QueryRoute': grpc.unary_unary_rpc_method_handler(
                     servicer.QueryRoute,
-                    
request_deserializer=service__pb2.QueryRouteRequest.FromString,
-                    
response_serializer=service__pb2.QueryRouteResponse.SerializeToString,
+                    
request_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.QueryRouteRequest.FromString,
+                    
response_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.QueryRouteResponse.SerializeToString,
             ),
             'Heartbeat': grpc.unary_unary_rpc_method_handler(
                     servicer.Heartbeat,
-                    
request_deserializer=service__pb2.HeartbeatRequest.FromString,
-                    
response_serializer=service__pb2.HeartbeatResponse.SerializeToString,
+                    
request_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.HeartbeatRequest.FromString,
+                    
response_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.HeartbeatResponse.SerializeToString,
             ),
             'SendMessage': grpc.unary_unary_rpc_method_handler(
                     servicer.SendMessage,
-                    
request_deserializer=service__pb2.SendMessageRequest.FromString,
-                    
response_serializer=service__pb2.SendMessageResponse.SerializeToString,
+                    
request_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.SendMessageRequest.FromString,
+                    
response_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.SendMessageResponse.SerializeToString,
             ),
             'QueryAssignment': grpc.unary_unary_rpc_method_handler(
                     servicer.QueryAssignment,
-                    
request_deserializer=service__pb2.QueryAssignmentRequest.FromString,
-                    
response_serializer=service__pb2.QueryAssignmentResponse.SerializeToString,
+                    
request_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.QueryAssignmentRequest.FromString,
+                    
response_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.QueryAssignmentResponse.SerializeToString,
             ),
             'ReceiveMessage': grpc.unary_stream_rpc_method_handler(
                     servicer.ReceiveMessage,
-                    
request_deserializer=service__pb2.ReceiveMessageRequest.FromString,
-                    
response_serializer=service__pb2.ReceiveMessageResponse.SerializeToString,
+                    
request_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.ReceiveMessageRequest.FromString,
+                    
response_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.ReceiveMessageResponse.SerializeToString,
             ),
             'AckMessage': grpc.unary_unary_rpc_method_handler(
                     servicer.AckMessage,
-                    
request_deserializer=service__pb2.AckMessageRequest.FromString,
-                    
response_serializer=service__pb2.AckMessageResponse.SerializeToString,
+                    
request_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.AckMessageRequest.FromString,
+                    
response_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.AckMessageResponse.SerializeToString,
             ),
             'ForwardMessageToDeadLetterQueue': 
grpc.unary_unary_rpc_method_handler(
                     servicer.ForwardMessageToDeadLetterQueue,
-                    
request_deserializer=service__pb2.ForwardMessageToDeadLetterQueueRequest.FromString,
-                    
response_serializer=service__pb2.ForwardMessageToDeadLetterQueueResponse.SerializeToString,
+                    
request_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.ForwardMessageToDeadLetterQueueRequest.FromString,
+                    
response_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.ForwardMessageToDeadLetterQueueResponse.SerializeToString,
             ),
             'EndTransaction': grpc.unary_unary_rpc_method_handler(
                     servicer.EndTransaction,
-                    
request_deserializer=service__pb2.EndTransactionRequest.FromString,
-                    
response_serializer=service__pb2.EndTransactionResponse.SerializeToString,
+                    
request_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.EndTransactionRequest.FromString,
+                    
response_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.EndTransactionResponse.SerializeToString,
             ),
             'Telemetry': grpc.stream_stream_rpc_method_handler(
                     servicer.Telemetry,
-                    
request_deserializer=service__pb2.TelemetryCommand.FromString,
-                    
response_serializer=service__pb2.TelemetryCommand.SerializeToString,
+                    
request_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.TelemetryCommand.FromString,
+                    
response_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.TelemetryCommand.SerializeToString,
             ),
             'NotifyClientTermination': grpc.unary_unary_rpc_method_handler(
                     servicer.NotifyClientTermination,
-                    
request_deserializer=service__pb2.NotifyClientTerminationRequest.FromString,
-                    
response_serializer=service__pb2.NotifyClientTerminationResponse.SerializeToString,
+                    
request_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.NotifyClientTerminationRequest.FromString,
+                    
response_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.NotifyClientTerminationResponse.SerializeToString,
             ),
             'ChangeInvisibleDuration': grpc.unary_unary_rpc_method_handler(
                     servicer.ChangeInvisibleDuration,
-                    
request_deserializer=service__pb2.ChangeInvisibleDurationRequest.FromString,
-                    
response_serializer=service__pb2.ChangeInvisibleDurationResponse.SerializeToString,
+                    
request_deserializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.ChangeInvisibleDurationRequest.FromString,
+                    
response_serializer=apache_dot_rocketmq_dot_v2_dot_service__pb2.ChangeInvisibleDurationResponse.SerializeToString,
             ),
     }
     generic_handler = grpc.method_handlers_generic_handler(
@@ -335,8 +335,8 @@ class MessagingService(object):
             timeout=None,
             metadata=None):
         return grpc.experimental.unary_unary(request, target, 
'/apache.rocketmq.v2.MessagingService/QueryRoute',
-            service__pb2.QueryRouteRequest.SerializeToString,
-            service__pb2.QueryRouteResponse.FromString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.QueryRouteRequest.SerializeToString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.QueryRouteResponse.FromString,
             options, channel_credentials,
             insecure, call_credentials, compression, wait_for_ready, timeout, 
metadata)
 
@@ -352,8 +352,8 @@ class MessagingService(object):
             timeout=None,
             metadata=None):
         return grpc.experimental.unary_unary(request, target, 
'/apache.rocketmq.v2.MessagingService/Heartbeat',
-            service__pb2.HeartbeatRequest.SerializeToString,
-            service__pb2.HeartbeatResponse.FromString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.HeartbeatRequest.SerializeToString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.HeartbeatResponse.FromString,
             options, channel_credentials,
             insecure, call_credentials, compression, wait_for_ready, timeout, 
metadata)
 
@@ -369,8 +369,8 @@ class MessagingService(object):
             timeout=None,
             metadata=None):
         return grpc.experimental.unary_unary(request, target, 
'/apache.rocketmq.v2.MessagingService/SendMessage',
-            service__pb2.SendMessageRequest.SerializeToString,
-            service__pb2.SendMessageResponse.FromString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.SendMessageRequest.SerializeToString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.SendMessageResponse.FromString,
             options, channel_credentials,
             insecure, call_credentials, compression, wait_for_ready, timeout, 
metadata)
 
@@ -386,8 +386,8 @@ class MessagingService(object):
             timeout=None,
             metadata=None):
         return grpc.experimental.unary_unary(request, target, 
'/apache.rocketmq.v2.MessagingService/QueryAssignment',
-            service__pb2.QueryAssignmentRequest.SerializeToString,
-            service__pb2.QueryAssignmentResponse.FromString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.QueryAssignmentRequest.SerializeToString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.QueryAssignmentResponse.FromString,
             options, channel_credentials,
             insecure, call_credentials, compression, wait_for_ready, timeout, 
metadata)
 
@@ -403,8 +403,8 @@ class MessagingService(object):
             timeout=None,
             metadata=None):
         return grpc.experimental.unary_stream(request, target, 
'/apache.rocketmq.v2.MessagingService/ReceiveMessage',
-            service__pb2.ReceiveMessageRequest.SerializeToString,
-            service__pb2.ReceiveMessageResponse.FromString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.ReceiveMessageRequest.SerializeToString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.ReceiveMessageResponse.FromString,
             options, channel_credentials,
             insecure, call_credentials, compression, wait_for_ready, timeout, 
metadata)
 
@@ -420,8 +420,8 @@ class MessagingService(object):
             timeout=None,
             metadata=None):
         return grpc.experimental.unary_unary(request, target, 
'/apache.rocketmq.v2.MessagingService/AckMessage',
-            service__pb2.AckMessageRequest.SerializeToString,
-            service__pb2.AckMessageResponse.FromString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.AckMessageRequest.SerializeToString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.AckMessageResponse.FromString,
             options, channel_credentials,
             insecure, call_credentials, compression, wait_for_ready, timeout, 
metadata)
 
@@ -437,8 +437,8 @@ class MessagingService(object):
             timeout=None,
             metadata=None):
         return grpc.experimental.unary_unary(request, target, 
'/apache.rocketmq.v2.MessagingService/ForwardMessageToDeadLetterQueue',
-            
service__pb2.ForwardMessageToDeadLetterQueueRequest.SerializeToString,
-            service__pb2.ForwardMessageToDeadLetterQueueResponse.FromString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.ForwardMessageToDeadLetterQueueRequest.SerializeToString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.ForwardMessageToDeadLetterQueueResponse.FromString,
             options, channel_credentials,
             insecure, call_credentials, compression, wait_for_ready, timeout, 
metadata)
 
@@ -454,8 +454,8 @@ class MessagingService(object):
             timeout=None,
             metadata=None):
         return grpc.experimental.unary_unary(request, target, 
'/apache.rocketmq.v2.MessagingService/EndTransaction',
-            service__pb2.EndTransactionRequest.SerializeToString,
-            service__pb2.EndTransactionResponse.FromString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.EndTransactionRequest.SerializeToString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.EndTransactionResponse.FromString,
             options, channel_credentials,
             insecure, call_credentials, compression, wait_for_ready, timeout, 
metadata)
 
@@ -471,8 +471,8 @@ class MessagingService(object):
             timeout=None,
             metadata=None):
         return grpc.experimental.stream_stream(request_iterator, target, 
'/apache.rocketmq.v2.MessagingService/Telemetry',
-            service__pb2.TelemetryCommand.SerializeToString,
-            service__pb2.TelemetryCommand.FromString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.TelemetryCommand.SerializeToString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.TelemetryCommand.FromString,
             options, channel_credentials,
             insecure, call_credentials, compression, wait_for_ready, timeout, 
metadata)
 
@@ -488,8 +488,8 @@ class MessagingService(object):
             timeout=None,
             metadata=None):
         return grpc.experimental.unary_unary(request, target, 
'/apache.rocketmq.v2.MessagingService/NotifyClientTermination',
-            service__pb2.NotifyClientTerminationRequest.SerializeToString,
-            service__pb2.NotifyClientTerminationResponse.FromString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.NotifyClientTerminationRequest.SerializeToString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.NotifyClientTerminationResponse.FromString,
             options, channel_credentials,
             insecure, call_credentials, compression, wait_for_ready, timeout, 
metadata)
 
@@ -505,7 +505,7 @@ class MessagingService(object):
             timeout=None,
             metadata=None):
         return grpc.experimental.unary_unary(request, target, 
'/apache.rocketmq.v2.MessagingService/ChangeInvisibleDuration',
-            service__pb2.ChangeInvisibleDurationRequest.SerializeToString,
-            service__pb2.ChangeInvisibleDurationResponse.FromString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.ChangeInvisibleDurationRequest.SerializeToString,
+            
apache_dot_rocketmq_dot_v2_dot_service__pb2.ChangeInvisibleDurationResponse.FromString,
             options, channel_credentials,
             insecure, call_credentials, compression, wait_for_ready, timeout, 
metadata)
diff --git a/python/rocketmq/rpc_client.py b/python/rocketmq/rpc_client.py
new file mode 100644
index 00000000..420559c1
--- /dev/null
+++ b/python/rocketmq/rpc_client.py
@@ -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.
+
+import asyncio
+import time
+from datetime import timedelta
+
+import certifi
+from grpc import aio, ssl_channel_credentials
+from protocol import service_pb2
+from rocketmq import logger
+from rocketmq.protocol import service_pb2_grpc
+
+
+class RpcClient:
+    channel_options = [
+        ("grpc.max_send_message_length", -1),
+        ("grpc.max_receive_message_length", -1),
+        ("grpc.connect_timeout_ms", 3000),
+    ]
+
+    def __init__(self, endpoints: str, ssl_enabled: bool = True):
+        self.__endpoints = endpoints
+        self.__cert = certifi.contents().encode(encoding="utf-8")
+        if ssl_enabled:
+            self.__channel = aio.secure_channel(
+                endpoints,
+                ssl_channel_credentials(root_certificates=self.__cert),
+                options=RpcClient.channel_options,
+            )
+        else:
+            self.__channel = aio.insecure_channel(
+                endpoints, options=RpcClient.channel_options
+            )
+        self.__stub = service_pb2_grpc.MessagingServiceStub(self.__channel)
+        self.activity_nano_time = time.monotonic_ns()
+
+    def idle_duration(self):
+        return timedelta(
+            microseconds=(time.monotonic_ns() - self.activity_nano_time) / 1000
+        )
+
+    async def query_route(
+        self, request: service_pb2.QueryRouteRequest, timeout_seconds: int
+    ):
+        return await self.__stub.QueryRoute(request, timeout=timeout_seconds)
+
+    async def heartbeat(
+        self, request: service_pb2.HeartbeatRequest, timeout_seconds: int
+    ):
+        return await self.__stub.Heartbeat(request, timeout=timeout_seconds)
+
+    async def send_message(
+        self, request: service_pb2.SendMessageRequest, timeout_seconds: int
+    ):
+        return await self.__stub.SendMessage(request, timeout=timeout_seconds)
+
+    async def query_assignment(
+        self, request: service_pb2.QueryAssignmentRequest, timeout_seconds: int
+    ):
+        return await self.__stub.QueryAssignment(request, 
timeout=timeout_seconds)
+
+    async def ack_message(
+        self, request: service_pb2.AckMessageRequest, timeout_seconds: int
+    ):
+        return await self.__stub.AckMessage(request, timeout=timeout_seconds)
+
+    async def forward_message_to_dead_letter_queue(
+        self,
+        request: service_pb2.ForwardMessageToDeadLetterQueueRequest,
+        timeout_seconds: int,
+    ):
+        return await self.__stub.ForwardMessageToDeadLetterQueue(
+            request, timeout=timeout_seconds
+        )
+
+    async def end_transaction(
+        self, request: service_pb2.EndTransactionRequest, timeout_seconds: int
+    ):
+        return await self.__stub.EndTransaction(request, 
timeout=timeout_seconds)
+
+    async def notify_client_termination(
+        self, request: service_pb2.NotifyClientTerminationRequest, 
timeout_seconds: int
+    ):
+        return await self.__stub.NotifyClientTermination(
+            request, timeout=timeout_seconds
+        )
+
+    async def change_invisible_duration(
+        self, request: service_pb2.ChangeInvisibleDurationRequest, 
timeout_seconds: int
+    ):
+        return await self.__stub.ChangeInvisibleDuration(
+            request, timeout=timeout_seconds
+        )
+
+
+async def test():
+    client = RpcClient("rmq-cn-72u353icd01.cn-hangzhou.rmq.aliyuncs.com:8080")
+    request = service_pb2.QueryRouteRequest()
+    response = await client.query_route(request, 3)
+    logger.info(response)
+
+
+if __name__ == "__main__":
+    asyncio.run(test())
diff --git a/python/protocol/__init__.py b/python/tests/__init__.py
similarity index 95%
rename from python/protocol/__init__.py
rename to python/tests/__init__.py
index 2bbe709e..ae1e83ee 100644
--- a/python/protocol/__init__.py
+++ b/python/tests/__init__.py
@@ -4,11 +4,11 @@
 # The ASF licenses this file to You under the Apache License, Version 2.0
 # (the "License"); you may not use this file except in compliance with
 # the License.  You may obtain a copy of the License at
-# 
+#
 #     http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT 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
+# limitations under the License.
diff --git a/python/protocol/definition_pb2_grpc.py b/python/tests/test_foo.py
similarity index 82%
rename from python/protocol/definition_pb2_grpc.py
rename to python/tests/test_foo.py
index 2cd6c817..70b00f6a 100644
--- a/python/protocol/definition_pb2_grpc.py
+++ b/python/tests/test_foo.py
@@ -4,16 +4,19 @@
 # The ASF licenses this file to You under the Apache License, Version 2.0
 # (the "License"); you may not use this file except in compliance with
 # the License.  You may obtain a copy of the License at
-# 
+#
 #     http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT 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 gRPC Python protocol compiler plugin. DO NOT EDIT!
-"""Client and server classes corresponding to protobuf-defined services."""
-import grpc
+from rocketmq import foo, logger
 
+
+def test_passing():
+    assert (1, 2, 3) == (1, 2, 3)
+    logger.info("foo.bar=%d", foo.bar)
+    logger.info("test_passing")

Reply via email to