异步调用组件

更新时间:
2024-05-15
下载文档

异步调用组件

本节内容介绍异步调用组件(AsyncCallMCom)的使用方法。异步调用组件可以发起一次或多次 VSOA-CALL 调用请求,组件收到所有调用请求之后触发 COM_FIN 事件。用户可以在 VSOA-CALL 调用请求响应接口缓存结果,然后在 COM_FIN 事件接口访问所有请求数据。

开发须知

  1. 本节示例可以从工程模板 demo-asynccall 创建工程。

  2. 本示例演示通过异步调用组件向其它服务发起请求,并将请求结果处理后返回调用者。

  3. 本节内容仅对异步调用组件的基本使用展开介绍,更详细的使用请参考工程建模-异步调用组件。 异步调用组件的使用请参考异步调用组件

服务模型

本示例由 4 个服务组成,展示异步 RPC 调用功能。

说明:

  • serc1serc2 发起 RPC 调用。
  • serc2 接收到 serc1 RPC 请求后,分别向 serc3serc4 发起 RPC 请求。
  • serc3serc4 接收到 serc2 RPC 请求后,分别返回结果。
  • serc2 接收到 serc3serc4 返回结果后,将计算处理的结果返回 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 组件中定义了一个异步调用组件 com1com1 接收 serc1 RPC 请示,同时向 serc3serc4 发起 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_setac_data_get 会话对象 API 缓存数据,关于会话对象缓存数据 API 请参考会话数据处理

文档内容是否对您有所帮助?
有帮助
没帮助