Skip to content

Commit

Permalink
docs: add aimrt_py rpc context (AimRT#58)
Browse files Browse the repository at this point in the history
* docs: clarify context type enumeration description

Enhance the explanation of the `aimrt_channel_context_type_t` enumeration to clearly indicate its role in defining publisher and subscriber contexts. This improves understanding for users implementing the interface.

* feat: enhance RpcContext with additional features

Add new methods for managing context metadata, timeout settings, and target addresses. Improve logging to provide better visibility into RPC calls and responses, aiding in debugging and performance monitoring.

* feat: enhance RPC context logging with metadata

Add the ability to log metadata in RPC calls, improving traceability and debugging. Update the client to set a metadata value and enhance server logging to print out all metadata associated with requests.

* feat: add RPC context types to Python bindings

Introduce enum values for client and server RPC context types in Python bindings to enhance type support and improve clarity in interactions with RPC features.
  • Loading branch information
zhangyi1357 authored Oct 28, 2024
1 parent 0b2427d commit 328a995
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 11 deletions.
2 changes: 1 addition & 1 deletion document/sphinx-cn/tutorials/interface_py/channel.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ protoc --python_out=. example.proto

`ContextRef``Context`的引用类型,除不具备`Reset`接口外,其他接口与`Context`完全相同。

`aimrt_channel_context_type_t` 是一个枚举类型,定义了上下文类型,具体值为`AIMRT_CHANNEL_PUBLISHER_CONTEXT``AIMRT_CHANNEL_SUBSCRIBER_CONTEXT`
`aimrt_channel_context_type_t` 是一个枚举类型,定义了上下文类型,具体值为`AIMRT_CHANNEL_PUBLISHER_CONTEXT``AIMRT_CHANNEL_SUBSCRIBER_CONTEXT`,表明这是发布者还是订阅者的上下文


## 使用示例
Expand Down
49 changes: 45 additions & 4 deletions document/sphinx-cn/tutorials/interface_py/rpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,30 @@ protoc --aimrt_rpc_out=. --plugin=protoc-gen-aimrt_rpc=./protoc_plugin_py_gen_ai

请注意,`RpcStatus`中的错误信息一般仅表示框架层面的错误,例如服务未找到、网络错误或者序列化错误等,供开发者排查框架层面的问题。如果开发者需要返回业务层面的错误,建议在业务包中添加相应的字段。

## RpcContext

RpcContext 是 RPC 调用时上下文信息,开发者可以在 RPC 调用时设置一些上下文信息,例如超时时间、Meta 信息等,具体接口如下:
- `CheckUsed()->bool` :检查 Context 是否被使用;
- `SetUsed()->None` :设置 Context 为已使用;
- `Reset()->None` :重置 Context;
- `GetType()->aimrt_rpc_context_type_t` :获取 Context 类型;
- `Timeout()->datetime.timedelta` :获取超时时间;
- `SetTimeout(timeout: datetime.timedelta)->None` :设置超时时间;
- `SetMetaValue(key: str, value: str)->None` :设置元数据;
- `GetMetaValue(key: str)->str` :获取元数据;
- `GetMetaKeys()->List[str]` :获取所有元数据键值对中的键列表;
- `SetToAddr(addr: str)->None` :设置目标地址;
- `GetToAddr()->str` :获取目标地址;
- `SetSerializationType(serialization_type: str)->None` :设置序列化类型;
- `GetSerializationType()->str` :获取序列化类型;
- `GetFunctionName()->str` :获取函数名称;
- `SetFunctionName(func_name: str)->None` :设置函数名称;
- `ToString()->str` :获取上下文信息,以字符串形式返回可读性高的信息;

`RpcContextRef``RpcContext`的引用类型,除不具备`Reset`接口外,其他接口与`RpcContext`完全相同。

`aimrt_rpc_context_type_t` 是一个枚举类型,定义了上下文类型,具体值为`AIMRT_RPC_CLIENT_CONTEXT``AIMRT_RPC_SERVER_CONTEXT`,表明这是客户端还是服务端的上下文。


## Client

Expand Down Expand Up @@ -147,11 +171,14 @@ def main():

ctx = aimrt_py.RpcContext()
ctx.SetTimeout(datetime.timedelta(seconds=30))
ctx.SetMetaValue("key1", "value1")
status, rsp = proxy.GetFooData(ctx, req)

aimrt_py.info(module_handle.GetLogger(),
"Call rpc done, status: {}, req: {}, rsp: {}"
.format(status.ToString(), MessageToJson(req), MessageToJson(rsp)))
f"Call rpc done, "
f"status: {status.ToString()}, "
f"req: {MessageToJson(req)}, "
f"rsp: {MessageToJson(rsp)}")

# Shutdown
aimrt_core.Shutdown()
Expand Down Expand Up @@ -201,13 +228,27 @@ def signal_handler(sig, frame):


class ExampleServiceImpl(rpc_aimrt_rpc_pb2.ExampleService):
def __init__(self):
def __init__(self, logger):
super().__init__()
self.logger = logger

@staticmethod
def PrintMetaInfo(logger, ctx_ref):
meta_keys = ctx_ref.GetMetaKeys()
for key in meta_keys:
aimrt_py.info(logger, f"meta key: {key}, value: {ctx_ref.GetMetaValue(key)}")

def GetFooData(self, ctx_ref, req):
rsp = rpc_pb2.GetFooDataRsp()
rsp.msg = "echo " + req.msg

ExampleServiceImpl.PrintMetaInfo(self.logger, ctx_ref)
aimrt_py.info(self.logger,
f"Server handle new rpc call. "
f"context: {ctx_ref.ToString()}, "
f"req: {MessageToJson(req)}, "
f"return rsp: {MessageToJson(rsp)}")

return aimrt_py.RpcStatus(), rsp

def main():
Expand All @@ -228,7 +269,7 @@ def main():
module_handle = aimrt_core.CreateModule("NormalRpcServerPymodule")

# Register rpc service
service = ExampleServiceImpl()
service = ExampleServiceImpl(module_handle.GetLogger())
ret = module_handle.GetRpcHandle().RegisterService(service)
assert ret, "Register service failed."

Expand Down
6 changes: 4 additions & 2 deletions src/examples/py/pb_rpc/examples_py_pb_rpc_client_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ def main():

ctx = aimrt_py.RpcContext()
ctx.SetTimeout(datetime.timedelta(seconds=30))
ctx.SetMetaValue("key1", "value1")
status, rsp = proxy.GetFooData(ctx, req)

aimrt_py.info(module_handle.GetLogger(),
"Call rpc done, status: {}, req: {}, rsp: {}"
.format(status.ToString(), MessageToJson(req), MessageToJson(rsp)))
f"Call rpc done, status: {status.ToString()}, "
f"req: {MessageToJson(req)}, "
f"rsp: {MessageToJson(rsp)}")

# Shutdown
aimrt_core.Shutdown()
Expand Down
20 changes: 16 additions & 4 deletions src/examples/py/pb_rpc/examples_py_pb_rpc_server_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,35 @@ def __init__(self, logger):
super().__init__()
self.logger = logger

@staticmethod
def PrintMetaInfo(logger, ctx_ref):
meta_keys = ctx_ref.GetMetaKeys()
for key in meta_keys:
aimrt_py.info(logger, f"meta key: {key}, value: {ctx_ref.GetMetaValue(key)}")

def GetFooData(self, ctx_ref, req):
rsp = rpc_pb2.GetFooDataRsp()
rsp.msg = "echo " + req.msg

ExampleServiceImpl.PrintMetaInfo(self.logger, ctx_ref)
aimrt_py.info(self.logger,
"Server handle new rpc call. context:{}, req: {}, return rsp: {}"
.format(ctx_ref.ToString(), MessageToJson(req), MessageToJson(rsp)))
f"Server handle new rpc call. "
f"context: {ctx_ref.ToString()}, "
f"req: {MessageToJson(req)}, "
f"return rsp: {MessageToJson(rsp)}")

return aimrt_py.RpcStatus(), rsp

def GetBarData(self, ctx_ref, req):
rsp = rpc_pb2.GetBarDataRsp()
rsp.msg = "echo " + req.msg

ExampleServiceImpl.PrintMetaInfo(self.logger, ctx_ref)
aimrt_py.info(self.logger,
"Server handle new rpc call. context:{}, req: {}, return rsp: {}"
.format(ctx_ref.ToString(), MessageToJson(req), MessageToJson(rsp)))
f"Server handle new rpc call. "
f"context: {ctx_ref.ToString()}, "
f"req: {MessageToJson(req)}, "
f"return rsp: {MessageToJson(rsp)}")

return aimrt_py.RpcStatus(), rsp

Expand Down
5 changes: 5 additions & 0 deletions src/runtime/python_runtime/export_rpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "python_runtime/export_type_support.h"

#include "pybind11/pybind11.h"
#include "rpc/rpc_context_base.h"

namespace aimrt::runtime::python_runtime {

Expand Down Expand Up @@ -58,6 +59,10 @@ inline void ExportRpcContext(const pybind11::object& m) {
using aimrt::rpc::Context;
using aimrt::rpc::ContextRef;

pybind11::enum_<aimrt_rpc_context_type_t>(m, "RpcContextType")
.value("AIMRT_RPC_CLIENT_CONTEXT", AIMRT_RPC_CLIENT_CONTEXT)
.value("AIMRT_RPC_SERVER_CONTEXT", AIMRT_RPC_SERVER_CONTEXT);

pybind11::class_<Context, std::shared_ptr<Context>>(m, "RpcContext")
.def(pybind11::init<>())
.def("CheckUsed", &Context::CheckUsed)
Expand Down

0 comments on commit 328a995

Please sign in to comment.