7. 使用事件订阅功能¶
在使用超级链的过程中,可能会遇到一些异步的情况:比如执行合约的时候,构造的交易是否合法我们可以实时获知,但具体什么时候真正的被节点打包上链就不一样了。当然还有其他类似的场景,针对这种问题,我们引入了事件订阅机制。
7.1. 事件订阅的接口¶
订阅的接口十分简单,只有subscribe和unsubscribe两个,订阅和取消订阅
1 2 3 4 | service PubsubService {
rpc Subscribe (EventRequest) returns (stream Event);
rpc Unsubscribe (UnsubscribeRequest) returns (UnsubscribeResponse) {}
}
|
其中订阅接口的EventRequest格式如下:
1 2 3 4 5 6 7 8 9 10 11 12 | message EventRequest {
EventType type = 1;
bytes payload = 2;
}
// EventType 主要有区块、交易、账户 3种
enum EventType {
UNDEFINED = 0;
BLOCK = 1;
TRANSACTION = 2;
ACCOUNT = 3;
SUBSCRIBE_RESPONSE = 4;
}
|
请求里的payload是一段序列化的proto对象,因为订阅不同内容需要的参数不尽相同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // BlockEventRequest 订阅区块请求
message BlockEventRequest {
string bcname = 1;
string proposer = 2;
int64 start_height = 3;
int64 end_height = 4;
bool need_content = 5;
}
// TransactionEventRequest 订阅交易请求
message TransactionEventRequest {
string bcname = 1;
string initiator = 2;
string auth_require = 3;
bool need_content = 4;
}
// AccountEventRequest 订阅账户请求
message AccountEventRequest {
string bcname = 1;
string from_addr = 2;
string to_addr = 3;
bool need_content = 4;
}
|
订阅返回的内容格式均为Event,对应不同的订阅类型填充不同的StatusInfo字段,详细内容会放在payload里
1 2 3 4 5 6 7 8 | message Event {
string id = 1;
EventType type = 2;
bytes payload = 3;
BlockStatusInfo block_status = 4;
TransactionStatusInfo tx_status = 5;
AccountStatusInfo account_status = 6;
}
|
订阅区块时,填充BlockEventRequest的链名、矿工地址、起止高度、以及是否需要详细内容字段。在订阅高度内,每当此矿工打包出块,便会接收到区块的内容
1 2 3 4 5 6 | message BlockStatusInfo {
string bcname = 1;
string proposer = 2;
int64 height = 3;
BlockStatus status = 4;
}
|
订阅交易时,可填充TransactionEventRequest的链名、发起方、签名方、以及是否需要详细内容字段,订阅开始后,由指定的账号发起或者有指定账号签名(注意两个条件是逻辑或的关系),便会收到交易内容
1 2 3 4 5 6 | message TransactionStatusInfo {
string bcname = 1;
string initiator = 2;
repeated string auth_require = 3;
TransactionStatus status = 4;
}
|
订阅账号时,可填充AccountEventRequest的链名、来源方、接收方、以及是否需要详细内容字段,订阅开始后,来源指定账号或者由指定账号接收的(注意两个条件是逻辑或的关系)交易内容均可以收到
1 2 3 4 5 6 | message AccountStatusInfo {
string bcname = 1;
repeated string from_addr = 2;
repeated string to_addr = 3;
TransactionStatus status = 4;
}
|
三种模式成功订阅后,都可以收到一个全局唯一的订阅id,使用这个id可以构造请求取消此订阅
1 2 3 4 | // UnsubscribeRequest 取消事件订阅请求
message UnsubscribeRequest {
string id = 1;
}
|
当然,进行订阅的进程退出或被杀死,订阅行为也会停止
7.2. 使用事件订阅¶
我们在xchain的代码中实现了一个简单的例子,参考 xuperchain/xuperchain/core/test/pubsub 目录,里面有一个示例程序和不同类别订阅需要的参数json文件
正常编译xchain即可获得此demo的可执行文件 event_client,按如下命令执行即可
1 2 | ./event_client -c subscribe -f accountEventSubscribe.json -h localhost:37101
./event_client -c unsubscribe -id xxxxxxxxxxxxxxxxxxx
|
示例程序中调用的便是上一小节介绍的订阅rpc接口