异步调用组件
本节内容介绍异步调用组件(AsyncCallMCom)的使用方法。异步调用组件可以发起一次或多次 VSOA-CALL 调用请求,组件收到所有调用请求之后触发 COM_FIN 事件。用户可以在 VSOA-CALL 调用请求响应接口缓存结果,然后在 COM_FIN 事件接口访问所有请求数据。
开发须知
本节示例可以从工程模板
demo-asynccall
创建工程。本示例演示通过异步调用组件向其它服务发起请求,并将请求结果处理后返回调用者。
本节内容仅对异步调用组件的基本使用展开介绍,更详细的使用请参考工程建模-异步调用组件。 异步调用组件的使用请参考异步调用组件。
服务模型
本示例由 4 个服务组成,展示异步 RPC 调用功能。
说明:
serc1
向serc2
发起 RPC 调用。serc2
接收到serc1
RPC 请求后,分别向serc3
,serc4
发起 RPC 请求。serc3
,serc4
接收到serc2
RPC 请求后,分别返回结果。serc2
接收到serc3
,serc4
返回结果后,将计算处理的结果返回serc1
。
组件模型与接口
serc1 组件
serc1
组件中定义了一个定时器事件,每 1 秒向 serc2
请求一次 RPC。
com1.event1
RPC reply 接口中打印接收的结果。
/*
* @func: serc1_com1_event1_vres_i
* @thread: serc2-client
*/
ac_result_t serc1_com1_event1_vres_i(ac_t *acs, vsoa_header_t *hdr, result_t *param, void *data, size_t len)
{
ac_result_t ret = AC_RET_OK;
/*---------------------------------------------------------------------------------------------------
* @begin: HANDLE_REPLY
* @desc: make you code below to handle input data.
you should check hdr, hdr->status, param;
reply timeout if hdr == NULL; param: maybe NULL if hdr->status error.
*-------------------------------------------------------------------------------------------------*/
printf("Rpc call result: %d\n", param->var1);
/*---------------------------------------------------------------------------------------------------
* @end: HANDLE_REPLY
*-------------------------------------------------------------------------------------------------*/
return (ret);
} /* @func-end */
serc2 组件
serc2
组件中定义了一个异步调用组件 com1
,com1
接收 serc1
RPC 请示,同时向 serc3
,serc4
发起 RPC 调用,最后在 finish
事件中向 serc1
返回 RPC 结果。
com1.event1
接口中,在会话上下文创建缓存。
/*
* @func: serc2_com1_event1_vcall_vreq_io
* @thread: serc2-service
*/
ac_result_t serc2_com1_event1_vcall_vreq_io(ac_t *acs, void *data, size_t len)
{
ac_result_t ret = AC_RET_OK;
bool call_ret = true;
vsoa_payload_t out;
ac_payload_init(&out, NULL, 0, data, len);
/*---------------------------------------------------------------------------------------------------
* @begin: HANDLE_INIT
* @desc: make you code below to handle input data, init output data.
*-------------------------------------------------------------------------------------------------*/
u_elems_t *cache = (u_elems_t *)malloc(sizeof(u_elems_t));
u_elems_init(cache);
ac_data_set(acs, "cache", (void *)cache, (ac_data_free_fun_t)free);
/*---------------------------------------------------------------------------------------------------
* @end: HANDLE_INIT
*-------------------------------------------------------------------------------------------------*/
call_ret = ac_port_call(acs, "/serc3/result", VSOA_CLIENT_RPC_METHOD_GET, 0, &out);
ret = call_ret ? AC_RET_OK : AC_RET_BREAK;
/*---------------------------------------------------------------------------------------------------
* @begin: FREE
* @desc: make you code below to free output data if needed.
*-------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------
* @end: FREE
*-------------------------------------------------------------------------------------------------*/
return (ret);
} /* @func-end */
com1.event1
RPC reply 接口中缓存结果。
/*
* @func: serc2_com1_event1_vres_i
* @thread: serc3-client
*/
ac_result_t serc2_com1_event1_vres_i(ac_t *acs, vsoa_header_t *hdr, result_t *param, void *data, size_t len)
{
ac_result_t ret = AC_RET_OK;
/*---------------------------------------------------------------------------------------------------
* @begin: HANDLE_REPLY
* @desc: make you code below to handle input data.
you should check hdr, hdr->status, param;
reply timeout if hdr == NULL; param: maybe NULL if hdr->status error.
*-------------------------------------------------------------------------------------------------*/
if (hdr && param) {
u_elems_t * cache = (u_elems_t *)ac_data_get(acs, "cache");
cache->elema = param->var1;
}
/*---------------------------------------------------------------------------------------------------
* @end: HANDLE_REPLY
*-------------------------------------------------------------------------------------------------*/
return (ret);
} /* @func-end */
com1.event2
RPC reply 接口与 com1.event1
RPC reply 接口处理类似。
com1.finish
接口从缓存中读取数据进行处理。
/*
* @func: serc2_com1_finish_cfin_i
* @thread: serc3-client | serc4-client
*/
ac_result_t serc2_com1_finish_cfin_i(ac_t *acs)
{
ac_result_t ret = AC_RET_OK;
bool reply_ret = true;
vsoa_payload_t reply;
uint8_t status = VSOA_STATUS_SUCCESS;
result_t _jreply;
result_t *jreply = &_jreply;
ac_payload_init(&reply, NULL, 0, NULL, 0);
result_init(jreply);
/*---------------------------------------------------------------------------------------------------
* @begin: HANDLE_INIT
* @desc: make you code below to handle input data, init output data.
*-------------------------------------------------------------------------------------------------*/
u_elems_t * cache = (u_elems_t *)ac_data_get(acs, "cache");
jreply->var1 = cache->elema + cache->elemb;
/*---------------------------------------------------------------------------------------------------
* @end: HANDLE_INIT
*-------------------------------------------------------------------------------------------------*/
reply.param = result_json_stringify(jreply);
reply.param_len = strlen(reply.param);
reply_ret = ac_port_reply(acs, status, &reply);
result_json_stringify_free(reply.param);
ret = reply_ret ? AC_RET_OK : AC_RET_BREAK;
/*---------------------------------------------------------------------------------------------------
* @begin: FREE
* @desc: make you code below to free output data if needed.
*-------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------
* @end: FREE
*-------------------------------------------------------------------------------------------------*/
return (ret);
} /* @func-end */
serc3 组件
serc3
接收 RPC 请求。
serc3.event1
接口中返回 RPC 结果。
/*
* @func: serc3_com1_event1_vcall_i
* @thread: serc3-service
*/
ac_result_t serc3_com1_event1_vcall_i(ac_t *acs, void *data, size_t len)
{
ac_result_t ret = AC_RET_OK;
bool reply_ret = true;
vsoa_payload_t reply;
uint8_t status = VSOA_STATUS_SUCCESS;
result_t _jreply;
result_t *jreply = &_jreply;
ac_payload_init(&reply, NULL, 0, NULL, 0);
result_init(jreply);
/*---------------------------------------------------------------------------------------------------
* @begin: HANDLE_INIT
* @desc: make you code below to handle input data, init output data.
*-------------------------------------------------------------------------------------------------*/
jreply->var1 = 100;
/*---------------------------------------------------------------------------------------------------
* @end: HANDLE_INIT
*-------------------------------------------------------------------------------------------------*/
reply.param = result_json_stringify(jreply);
reply.param_len = strlen(reply.param);
reply_ret = ac_port_reply(acs, status, &reply);
result_json_stringify_free(reply.param);
ret = reply_ret ? AC_RET_OK : AC_RET_BREAK;
/*---------------------------------------------------------------------------------------------------
* @begin: FREE
* @desc: make you code below to free output data if needed.
*-------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------
* @end: FREE
*-------------------------------------------------------------------------------------------------*/
return (ret);
} /* @func-end */
serc4
组件模型及接口与 serc3
类似。
运行结果
serc1
每秒请求一次数据,运行结果如下图展示。
注意
通过配置事件的
reply
属性,可以选择 RPC reply 执行时机。reply
属性介绍请参考 VSOA-CALL 事件。 接口使用了ac_data_set
和ac_data_get
会话对象 API 缓存数据,关于会话对象缓存数据 API 请参考会话数据处理。