PageSourceSearch

https://atframe.work/en/assets/js/1f8f12da.5e88d55b.js

js atframe.work collected 2026-09-25 22:31:56 UTC 6,225 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkatsf4g_co_docs||=[]).push([[3712],{1984(e,s,n){n.r(s),n.d(s,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>o});const r=JSON.parse('{"id":"development/add-rpc-task","title":"Adding RPC and Task Actions","description":"SS RPC (service-to-service)","source":"@site/i18n/en/docusaurus-plugin-content-docs/current/development/add-rpc-task.md","sourceDirName":"development","slug":"/development/add-rpc-task","permalink":"/en/development/add-rpc-task","draft":false,"unlisted":false,"editUrl":"https://github.com/atframework/atsf4g-co/edit/main/doc/docs/development/add-rpc-task.md","tags":[],"version":"current","frontMatter":{"title":"Adding RPC and Task Actions"},"sidebar":"docs","previous":{"title":"Adding a Service","permalink":"/en/development/add-service"},"next":{"title":"Adding a Database Table","permalink":"/en/development/add-db-table"}}');var t=n(6070),d=n(3797);const i={title:"Adding RPC and Task Actions"},c="Adding RPC and Task Actions",a={},o=[{value:"SS RPC (service-to-service)",id:"ss-rpc-service-to-service",level:2},{value:"CS RPC (client)",id:"cs-rpc-client",level:2},{value:"Messageless Tasks",id:"messageless-tasks",level:2},{value:"Common Options",id:"common-options",level:2}];function l(e){const s={code:"code",h1:"h1",h2:"h2",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,d.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(s.header,{children:(0,t.jsx)(s.h1,{id:"adding-rpc-and-task-actions",children:"Adding RPC and Task Actions"})}),"\n",(0,t.jsx)(s.h2,{id:"ss-rpc-service-to-service",children:"SS RPC (service-to-service)"}),"\n",(0,t.jsxs)(s.ol,{children:["\n",(0,t.jsx)(s.li,{children:"Add a method to an existing service (or a new service) in the proto:"}),"\n"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-protobuf",children:'service MyService {\r\n  option (atframework.service_options) = {module_name: "my_module"};\r\n  rpc my_method(MyMethodReq) returns (MyMethodRsp) {\r\n    option (atframework.rpc_options) = {api_name: "my_method" allow_no_wait: false};\r\n  }\r\n}\n'})}),"\n",(0,t.jsxs)(s.ol,{start:"2",children:["\n",(0,t.jsxs)(s.li,{children:["Rebuild: protoc + mako-generator automatically produce:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["the server-side task action skeleton ",(0,t.jsx)(s.code,{children:"task_action_my_method.{h,cpp}"})," (existing handwritten parts are\r\npreserved within marked regions);"]}),"\n",(0,t.jsxs)(s.li,{children:["updated handler registration ",(0,t.jsx)(s.code,{children:"handle_ss_rpc_<service>.atfw.gen.*"}),";"]}),"\n",(0,t.jsxs)(s.li,{children:["the caller-side API ",(0,t.jsx)(s.code,{children:"rpc_call_api"})," (",(0,t.jsx)(s.code,{children:"<service>.atfw.gen.*"}),")."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Implement the business logic in the skeleton's ",(0,t.jsx)(s.code,{children:"operator()"}),":"]}),"\n"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-cpp",children:"task_action_my_method::result_type task_action_my_method::operator()() {\r\n  MyMethodRsp &rsp = get_response_body();\r\n  // ... business logic; may use RPC_AWAIT_CODE_RESULT(rpc::db::xxx(...))\r\n  RPC_RETURN_CODE(0);\r\n}\n"})}),"\n",(0,t.jsxs)(s.ol,{start:"4",children:["\n",(0,t.jsx)(s.li,{children:"Caller side:"}),"\n"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-cpp",children:"MyMethodReq req;\r\n// ... fill in the request\r\nauto res = RPC_AWAIT_CODE_RESULT(rpc::MyService::my_method(ctx, req, /*target*/...));\n"})}),"\n",(0,t.jsx)(s.h2,{id:"cs-rpc-client",children:"CS RPC (client)"}),"\n",(0,t.jsxs)(s.p,{children:["Define messages and services in ",(0,t.jsx)(s.code,{children:"com.protocol*.proto"})," (public), and declare the ",(0,t.jsx)(s.code,{children:"handle_cs_rpc"})," /\r\n",(0,t.jsx)(s.code,{children:"task_action_cs_rpc"})," templates in CMake; the generated action base class is ",(0,t.jsx)(s.code,{children:"task_action_cs_req_base"}),",\r\nwhich comes with session validation and downstream packing built in. The downstream push API is generated by\r\n",(0,t.jsx)(s.code,{children:"session_downstream_api_for_cs.*.mako"}),"."]}),"\n",(0,t.jsx)(s.h2,{id:"messageless-tasks",children:"Messageless Tasks"}),"\n",(0,t.jsxs)(s.p,{children:["Scheduled/self-driven tasks use the ",(0,t.jsx)(s.code,{children:"task_action_no_msg.*.mako"})," template, or use\r\n",(0,t.jsx)(s.code,{children:"src/generate-nomsg-task.sh"})," (",(0,t.jsx)(s.code,{children:".in"}),") to quickly generate a skeleton; an in-framework example:\r\n",(0,t.jsx)(s.code,{children:"task_action_auto_save_objects"}),"."]}),"\n",(0,t.jsx)(s.h2,{id:"common-options",children:"Common Options"}),"\n",(0,t.jsxs)(s.table,{children:[(0,t.jsx)(s.thead,{children:(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.th,{children:"rpc_options"}),(0,t.jsx)(s.th,{children:"Effect"})]})}),(0,t.jsxs)(s.tbody,{children:[(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"allow_no_wait: true"})}),(0,t.jsxs)(s.td,{children:["The caller only sends without waiting for a response 
1(no ",(0,t.jsx)(s.code,{children:"co_await"})," result)"]})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsxs)(s.td,{children:["stream return (",(0,t.jsx)(s.code,{children:"returns (stream X)"}),")"]}),(0,t.jsxs)(s.td,{children:["Server-side streaming downstream push (e.g., ",(0,t.jsx)(s.code,{children:"player_dirty_chg_sync"})," in ",(0,t.jsx)(s.code,{children:"com.protocol.proto"}),")"]})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsxs)(s.td,{children:["stream request (",(0,t.jsx)(s.code,{children:"rpc x(stream Req) returns (...)"}),")"]}),(0,t.jsxs)(s.td,{children:["Caller-side streaming upload / response-free calls (e.g., dtmq ",(0,t.jsx)(s.code,{children:"channel_event_sync"}),")"]})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"api_name"})}),(0,t.jsx)(s.td,{children:"The generated caller-side function name"})]})]})]})]})}function h(e={}){const{wrapper:s}={...(0,d.R)(),...e.components};return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.