# 订阅事件概述


# 业务场景

学校对接的应用业务对数据的实时性要求较高,希望能够及时地从校宝智慧校园同步数据的变化。例如当员工发生变更时,可以根据员工变更事件,处理变更的数据,而无需定期通过通讯录接口循环遍历处理员工信息。

# 配置应用事件

为了能够接收事件订阅消息,联系校宝工作人员配置请求地址URL。当应用订阅的事件触发时,开放平台会向该地址发送相应的HTTP(POST)请求。

每个接入方只能配置一个请求地址,订阅的所有事件通知都会发送到该请求地址。

收到开放平台HTTP(POST)请求时,需要有一个接口处理推送的事件信息,返回处理结果作为响应。

//响应内容如下
{
    "errcode":"@integer(60, 100)",//返回码,0代表正常
    "errmsg":"@string"//返回信息
}

请求地址URL示例:https://test.1gai.cn/api/demo/callback

# 接收并响应事件

当学校订阅的事件发生时,校宝智慧校园会通过HTTP(POST)请求发送Json格式的事件数据到预先提供的请求地址URL。

事件数据如下:

{
    "bizId":"@string",//业务Id,部分事件搭配接口不需要bizId时为空字符串
    "bizAction":"@string",//事件行为
    "corpId":"@string",//cropId
    "occurTime":"@datetime",//事件发生时间
}

收到此请求时,需要在5秒内http 200响应该请求,如果未及时相应,校宝智慧校园会进行重试推送,最多重试10次。

# 数据库设计参考建议

该数据库表结构仅供参考,核心字段只有bizId、bizAction、corpId、occurTime,其他可自行扩展。

/*==============================================================*/
/* Table: xiaobao_sync_biz_data                                 */
/*==============================================================*/
create table xiaobao_sync_biz_data
(
   id                   bigint(20) not null auto_increment comment '主键Id',
   bizId                varchar(128) not null default '' comment '业务Id',
   bizAction            varchar(128) not null default '' comment '订阅事件',
   corpId               varchar(128) not null default '' comment 'CorpId',
   status               tinyint(4) not null default 0 comment '状态,处理状态0为未处理。其他状态开发者自行定义',
   occurTime             datetime not null default CURRENT_TIMESTAMP comment '事件发生时间'
   primary key (id)
);
alter table xiaobao_sync_biz_data comment '校宝智慧校园事件推送表';

# 订阅事件数据处理伪代码

callback(syncModel model):
    //加锁。对每条消息加锁。保证每条推送消息同一时刻是有一个线程在处理。
    //如果开发者有多台机器,避免并发处理数据造成数据被并发重复处理。
    lock = tryLock(model);

    //如果获取锁失败,表示有其他线程在处理推送消息。返回
    //加锁是为了有多台机器或者多个线程同时处理推送消息的时候,避免发生并发问题。
    if !lock
        return

    try {
        //处理推数据入库,此处只做简单的入库处理,需要迅速返回结果给请求方。
        //可自行定义数据的处理状态,建议0为未处理状态。1为处理完成状态。2为处理失败状态。
        //消息的消费策略,需要在另一个服务中定义,根据status状态进行消费和重试。
        saveSyncModel(model);
    }
    catch {
        //此处要有监控报警。当发现程序异常,要报警。
        //建议日志记录下程序异常时正在处理的推送模型,方便后期排查和补录。
    }

    //返回响应信息
    return new ResponsModel(){errcode, errmsg};

# 订阅事件说明