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.