Skip to main content

RPC and Code Generation

Protocol as the Source of Truth​

All protocols are defined in protobuf, rooted at src/server_frame/protocol/:

protocol/
├── private/protocol/ # Server-internal only
│ ├── pbdesc/ # svr.protocol.proto (RouterService/LogicCommonService), svr.*.table.proto (DB tables)
│ ├── common/ config/ extension/ log/
└── public/protocol/ # Shareable with clients
├── extension/atframework.proto # Custom service/rpc options (drive code generation)
└── pbdesc/ com.protocol*.proto (CS/SS messages), com.struct*.proto (data structures)

All generated artifacts are regenerated, never edited by hand (*.atfw.gen.{h,cpp}, *.pb.{h,cc}, config/db code).

Custom Options​

The extension options that drive code generation are spread across three files:

  • public/protocol/extension/atframework.proto: atframework.service_options (module_name, etc.) and atframework.rpc_options (api_name, allow_no_wait, etc.);
  • protocol/extension/xrescode_extensions_v3.proto: the xrescode.loader option, marking Excel config loaders;
  • private/protocol/extension/svr.database.extension.proto: DB table/index extensions (KV/KL/CAS/TTL), used by the db templates.

Generation Pipeline​

  • src/server_frame/generate_proto_source.cmake / generate_proto_utility.cmake: protoc compilation;
  • src/tools/generate-for-pb/mako-generator.py: reads the pb descriptor set and renders in bulk according to the rules declared in each CMakeLists (service name + template + output path);
  • src/tools/generate_for_pb_utility.cmake: CMake-side wrapper for invoking templates.

Template Inventory (src/templates/)​

TemplateGenerated artifact
handle_ss_rpc.*.makoSS RPC registration function register_handles_for_<service>
task_action_ss_rpc.*.makoServer-side task action skeleton for each SS RPC method
rpc_call_api_for_ss.*.makoSS RPC client call APIs (unary/stream/no-wait/broadcast/metadata/user/router variants) and per-RPC full-name accessors
handle_cs_rpc.*.mako / task_action_cs_rpc.*.makoHandlers and task actions for client RPCs
session_downstream_api_for_cs.*.makoServer→client session downstream push APIs and per-RPC full-name accessors
package_request_api_for_simulator.*.makoCS request packing APIs for the robot/simulator
task_action_no_msg.*.makoNo-message task actions (used with src/generate-nomsg-task.sh)
db_interface.*.mako / db_rpc_redis(.kv/.kl).*.makoRedis database access layer (rpc/db/local_db_interface.atfw.gen.*)
config_manager.*.mako / config_set.*.mako / config_easy_api.*.makoExcel config loading framework and convenient read APIs

The orbit component has its own dedicated templates: src/component/orbit/sdk/server/template/ (they also generate per-RPC full-name accessors).

The SS template generates gsl::string_view get_full_name_of_<rpc>() inside the packer sub-namespace (alongside pack_<rpc>/unpack_<rpc>, declared in <service>.atfw.gen.h), returning the on-wire full RPC name (package.Service/method). The CS template generates it in the same packer sub-namespace. The orbit fork also uses the packer sub-namespace, returning its dotted protocol name. When registering SS mocks or asserting call history via test.ss(), use the SS/CS-template accessor instead of a hardcoded string (see RPC unit testing); the orbit-fork getter returns its dotted name and orbit RPCs traverse orbit transport (not the SS engine), so it must not be passed to test.ss().

RPC Caller API Shape​

Generated callers return awaitable objects:

// unary: suspends to wait for the response
auto res = RPC_AWAIT_CODE_RESULT(rpc::SomeService::some_rpc(ctx, req, ...));

// no-wait (rpc_options.allow_no_wait): send without waiting
// stream: server-side streaming push (e.g. dtmq's channel_event_sync)

Error handling convention: framework-level failures go through rpc::result_code_type (including HTTP-style error codes and PB unpacking errors); business error codes are defined in svr.const.err.proto / com.const.proto.