637 lines
18 KiB
Rust
637 lines
18 KiB
Rust
//! 事件通知系统
|
||
//!
|
||
//! 实现完整的事件通知功能,包括事件定义、事件触发、事件监听和事件日志
|
||
|
||
use std::sync::Arc;
|
||
|
||
/// ACC-1410事件类型
|
||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||
/// Acc1410Event 协议事件
|
||
pub enum Acc1410Event {
|
||
/// 分区创建事件
|
||
PartitionCreated {
|
||
/// 分区标识符
|
||
partition_id: [u8; 32],
|
||
/// 名称
|
||
name: String,
|
||
/// partition_type 字段
|
||
partition_type: u8,
|
||
},
|
||
/// 分区关闭事件
|
||
PartitionClosed {
|
||
/// 分区标识符
|
||
partition_id: [u8; 32],
|
||
},
|
||
/// 转账事件
|
||
Transfer {
|
||
/// 发送方账户地址
|
||
from: String,
|
||
/// 接收方账户地址
|
||
to: String,
|
||
/// 代币数量(最小单位)
|
||
amount: u64,
|
||
/// 分区标识符
|
||
partition_id: [u8; 32],
|
||
},
|
||
/// 铸造事件
|
||
Mint {
|
||
/// 接收方账户地址
|
||
to: String,
|
||
/// 代币数量(最小单位)
|
||
amount: u64,
|
||
/// 分区标识符
|
||
partition_id: [u8; 32],
|
||
},
|
||
/// 销毁事件
|
||
Burn {
|
||
/// 发送方账户地址
|
||
from: String,
|
||
/// 代币数量(最小单位)
|
||
amount: u64,
|
||
/// 分区标识符
|
||
partition_id: [u8; 32],
|
||
},
|
||
/// 操作员授权事件
|
||
OperatorAuthorized {
|
||
/// account 字段
|
||
account: String,
|
||
/// 操作员账户地址
|
||
operator: String,
|
||
/// 分区标识符
|
||
partition_id: Option<[u8; 32]>,
|
||
},
|
||
/// 操作员撤销事件
|
||
OperatorRevoked {
|
||
/// account 字段
|
||
account: String,
|
||
/// 操作员账户地址
|
||
operator: String,
|
||
/// 分区标识符
|
||
partition_id: Option<[u8; 32]>,
|
||
},
|
||
/// 账户锁定事件
|
||
AccountLocked {
|
||
/// account 字段
|
||
account: String,
|
||
/// unlock_time 字段
|
||
unlock_time: u64,
|
||
},
|
||
/// 账户解锁事件
|
||
AccountUnlocked {
|
||
/// account 字段
|
||
account: String,
|
||
},
|
||
/// 批量转账事件
|
||
BatchTransfer {
|
||
/// 发送方账户地址
|
||
from: String,
|
||
/// recipient_count 字段
|
||
recipient_count: usize,
|
||
/// 操作总金额
|
||
total_amount: u64,
|
||
/// 分区标识符
|
||
partition_id: [u8; 32],
|
||
},
|
||
/// 批量铸造事件
|
||
BatchMint {
|
||
/// recipient_count 字段
|
||
recipient_count: usize,
|
||
/// 操作总金额
|
||
total_amount: u64,
|
||
/// 分区标识符
|
||
partition_id: [u8; 32],
|
||
},
|
||
/// 批量销毁事件
|
||
BatchBurn {
|
||
/// account_count 字段
|
||
account_count: usize,
|
||
/// 操作总金额
|
||
total_amount: u64,
|
||
/// 分区标识符
|
||
partition_id: [u8; 32],
|
||
},
|
||
}
|
||
|
||
/// 事件记录
|
||
#[derive(Debug, Clone)]
|
||
/// EventRecord 协议事件
|
||
pub struct EventRecord {
|
||
/// 事件ID
|
||
pub event_id: u64,
|
||
/// 事件类型
|
||
pub event: Acc1410Event,
|
||
/// 时间戳
|
||
pub timestamp: u64,
|
||
/// 区块高度(可选)
|
||
pub block_height: Option<u64>,
|
||
/// 交易哈希 (SHA3-384 Hash)(可选)
|
||
pub tx_hash: Option<[u8; 48]>,
|
||
}
|
||
|
||
/// 事件监听器trait
|
||
pub trait EventListener: Send + Sync + std::fmt::Debug {
|
||
/// 处理事件
|
||
fn on_event(&self, event: &EventRecord);
|
||
|
||
/// 获取监听器名称
|
||
fn name(&self) -> &str;
|
||
}
|
||
|
||
/// 事件过滤器
|
||
#[derive(Debug, Clone)]
|
||
/// EventFilter 协议事件
|
||
pub struct EventFilter {
|
||
/// 事件类型过滤(None表示所有类型)
|
||
pub event_types: Option<Vec<String>>,
|
||
/// 账户过滤
|
||
pub accounts: Option<Vec<String>>,
|
||
/// 分区过滤
|
||
pub partitions: Option<Vec<[u8; 32]>>,
|
||
/// 时间范围过滤
|
||
pub time_range: Option<(u64, u64)>,
|
||
}
|
||
|
||
/// 事件管理器
|
||
#[derive(Debug)]
|
||
/// EventManager 协议事件
|
||
pub struct EventManager {
|
||
/// 事件日志
|
||
event_log: Vec<EventRecord>,
|
||
/// 事件监听器
|
||
listeners: Vec<Arc<dyn EventListener>>,
|
||
/// 事件计数器
|
||
event_counter: u64,
|
||
/// 最大日志大小
|
||
max_log_size: usize,
|
||
}
|
||
|
||
impl EventManager {
|
||
/// 创建新的事件管理器
|
||
pub fn new() -> Self {
|
||
Self {
|
||
event_log: Vec::new(),
|
||
listeners: Vec::new(),
|
||
event_counter: 0,
|
||
max_log_size: 10000,
|
||
}
|
||
}
|
||
|
||
/// 设置最大日志大小
|
||
pub fn set_max_log_size(&mut self, size: usize) {
|
||
self.max_log_size = size;
|
||
}
|
||
|
||
/// 添加事件监听器
|
||
pub fn add_listener(&mut self, listener: Arc<dyn EventListener>) {
|
||
self.listeners.push(listener);
|
||
}
|
||
|
||
/// 移除事件监听器
|
||
pub fn remove_listener(&mut self, name: &str) {
|
||
self.listeners.retain(|l| l.name() != name);
|
||
}
|
||
|
||
/// 触发事件
|
||
pub fn emit_event(&mut self, event: Acc1410Event) {
|
||
self.emit_event_with_details(event, None, None);
|
||
}
|
||
|
||
/// 触发事件(带详细信息)
|
||
pub fn emit_event_with_details(
|
||
&mut self,
|
||
event: Acc1410Event,
|
||
block_height: Option<u64>,
|
||
tx_hash: Option<[u8; 48]>,
|
||
) {
|
||
self.event_counter += 1;
|
||
|
||
let record = EventRecord {
|
||
event_id: self.event_counter,
|
||
event,
|
||
timestamp: Self::current_timestamp(),
|
||
block_height,
|
||
tx_hash,
|
||
};
|
||
|
||
// 通知所有监听器
|
||
for listener in &self.listeners {
|
||
listener.on_event(&record);
|
||
}
|
||
|
||
// 添加到日志
|
||
self.event_log.push(record);
|
||
|
||
// 如果日志超过最大大小,移除最老的事件
|
||
if self.event_log.len() > self.max_log_size {
|
||
self.event_log.remove(0);
|
||
}
|
||
}
|
||
|
||
/// 查询事件
|
||
pub fn query_events(&self, filter: &EventFilter) -> Vec<EventRecord> {
|
||
self.event_log
|
||
.iter()
|
||
.filter(|record| self.matches_filter(record, filter))
|
||
.cloned()
|
||
.collect()
|
||
}
|
||
|
||
/// 获取最近的事件
|
||
pub fn get_recent_events(&self, count: usize) -> Vec<EventRecord> {
|
||
let start = if self.event_log.len() > count {
|
||
self.event_log.len() - count
|
||
} else {
|
||
0
|
||
};
|
||
self.event_log[start..].to_vec()
|
||
}
|
||
|
||
/// 获取账户相关的事件
|
||
pub fn get_account_events(&self, account: &str) -> Vec<EventRecord> {
|
||
self.event_log
|
||
.iter()
|
||
.filter(|record| self.event_involves_account(record, account))
|
||
.cloned()
|
||
.collect()
|
||
}
|
||
|
||
/// 获取分区相关的事件
|
||
pub fn get_partition_events(&self, partition_id: &[u8; 32]) -> Vec<EventRecord> {
|
||
self.event_log
|
||
.iter()
|
||
.filter(|record| self.event_involves_partition(record, partition_id))
|
||
.cloned()
|
||
.collect()
|
||
}
|
||
|
||
/// 清空事件日志
|
||
pub fn clear_log(&mut self) {
|
||
self.event_log.clear();
|
||
}
|
||
|
||
/// 获取事件统计
|
||
pub fn get_event_statistics(&self) -> EventStatistics {
|
||
let mut stats = EventStatistics::default();
|
||
|
||
for record in &self.event_log {
|
||
match &record.event {
|
||
Acc1410Event::PartitionCreated { .. } => stats.partition_created += 1,
|
||
Acc1410Event::PartitionClosed { .. } => stats.partition_closed += 1,
|
||
Acc1410Event::Transfer { .. } => stats.transfers += 1,
|
||
Acc1410Event::Mint { .. } => stats.mints += 1,
|
||
Acc1410Event::Burn { .. } => stats.burns += 1,
|
||
Acc1410Event::OperatorAuthorized { .. } => stats.operator_authorized += 1,
|
||
Acc1410Event::OperatorRevoked { .. } => stats.operator_revoked += 1,
|
||
Acc1410Event::AccountLocked { .. } => stats.account_locked += 1,
|
||
Acc1410Event::AccountUnlocked { .. } => stats.account_unlocked += 1,
|
||
Acc1410Event::BatchTransfer { .. } => stats.batch_transfers += 1,
|
||
Acc1410Event::BatchMint { .. } => stats.batch_mints += 1,
|
||
Acc1410Event::BatchBurn { .. } => stats.batch_burns += 1,
|
||
}
|
||
}
|
||
|
||
stats.total_events = self.event_log.len();
|
||
stats
|
||
}
|
||
|
||
/// 检查事件是否匹配过滤器
|
||
fn matches_filter(&self, record: &EventRecord, filter: &EventFilter) -> bool {
|
||
// 检查时间范围
|
||
if let Some((start, end)) = filter.time_range {
|
||
if record.timestamp < start || record.timestamp > end {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 检查账户
|
||
if let Some(accounts) = &filter.accounts {
|
||
if !accounts.iter().any(|acc| self.event_involves_account(record, acc)) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 检查分区
|
||
if let Some(partitions) = &filter.partitions {
|
||
if !partitions.iter().any(|p| self.event_involves_partition(record, p)) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
true
|
||
}
|
||
|
||
/// 检查事件是否涉及账户
|
||
fn event_involves_account(&self, record: &EventRecord, account: &str) -> bool {
|
||
match &record.event {
|
||
Acc1410Event::Transfer { from, to, .. } => from == account || to == account,
|
||
Acc1410Event::Mint { to, .. } => to == account,
|
||
Acc1410Event::Burn { from, .. } => from == account,
|
||
Acc1410Event::OperatorAuthorized { account: acc, .. } => acc == account,
|
||
Acc1410Event::OperatorRevoked { account: acc, .. } => acc == account,
|
||
Acc1410Event::AccountLocked { account: acc, .. } => acc == account,
|
||
Acc1410Event::AccountUnlocked { account: acc } => acc == account,
|
||
Acc1410Event::BatchTransfer { from, .. } => from == account,
|
||
_ => false,
|
||
}
|
||
}
|
||
|
||
/// 检查事件是否涉及分区
|
||
fn event_involves_partition(&self, record: &EventRecord, partition_id: &[u8; 32]) -> bool {
|
||
match &record.event {
|
||
Acc1410Event::PartitionCreated { partition_id: p, .. } => p == partition_id,
|
||
Acc1410Event::PartitionClosed { partition_id: p } => p == partition_id,
|
||
Acc1410Event::Transfer { partition_id: p, .. } => p == partition_id,
|
||
Acc1410Event::Mint { partition_id: p, .. } => p == partition_id,
|
||
Acc1410Event::Burn { partition_id: p, .. } => p == partition_id,
|
||
Acc1410Event::OperatorAuthorized { partition_id: p, .. } => {
|
||
p.as_ref() == Some(partition_id)
|
||
}
|
||
Acc1410Event::OperatorRevoked { partition_id: p, .. } => {
|
||
p.as_ref() == Some(partition_id)
|
||
}
|
||
Acc1410Event::BatchTransfer { partition_id: p, .. } => p == partition_id,
|
||
Acc1410Event::BatchMint { partition_id: p, .. } => p == partition_id,
|
||
Acc1410Event::BatchBurn { partition_id: p, .. } => p == partition_id,
|
||
_ => false,
|
||
}
|
||
}
|
||
|
||
/// 获取当前时间戳
|
||
fn current_timestamp() -> u64 {
|
||
use std::time::{SystemTime, UNIX_EPOCH};
|
||
SystemTime::now()
|
||
.duration_since(UNIX_EPOCH)
|
||
.unwrap()
|
||
.as_secs()
|
||
}
|
||
}
|
||
|
||
/// 事件统计
|
||
#[derive(Debug, Default, Clone)]
|
||
/// EventStatistics 协议事件
|
||
pub struct EventStatistics {
|
||
/// 总事件数
|
||
pub total_events: usize,
|
||
/// 分区创建事件数
|
||
pub partition_created: usize,
|
||
/// 分区关闭事件数
|
||
pub partition_closed: usize,
|
||
/// 转账事件数
|
||
pub transfers: usize,
|
||
/// 铸造事件数
|
||
pub mints: usize,
|
||
/// 销毁事件数
|
||
pub burns: usize,
|
||
/// 操作员授权事件数
|
||
pub operator_authorized: usize,
|
||
/// 操作员撤销事件数
|
||
pub operator_revoked: usize,
|
||
/// 账户锁定事件数
|
||
pub account_locked: usize,
|
||
/// 账户解锁事件数
|
||
pub account_unlocked: usize,
|
||
/// 批量转账事件数
|
||
pub batch_transfers: usize,
|
||
/// 批量铸造事件数
|
||
pub batch_mints: usize,
|
||
/// 批量销毁事件数
|
||
pub batch_burns: usize,
|
||
}
|
||
|
||
impl Default for EventManager {
|
||
fn default() -> Self {
|
||
Self::new()
|
||
}
|
||
}
|
||
|
||
/// 控制台事件监听器(用于测试)
|
||
#[derive(Debug)]
|
||
/// ConsoleEventListener 协议事件
|
||
pub struct ConsoleEventListener {
|
||
name: String,
|
||
}
|
||
|
||
impl ConsoleEventListener {
|
||
/// new 方法
|
||
pub fn new(name: String) -> Self {
|
||
Self { name }
|
||
}
|
||
}
|
||
|
||
impl EventListener for ConsoleEventListener {
|
||
fn on_event(&self, event: &EventRecord) {
|
||
println!("[{}] Event #{}: {:?}", self.name, event.event_id, event.event);
|
||
}
|
||
|
||
fn name(&self) -> &str {
|
||
&self.name
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_emit_event() {
|
||
let mut manager = EventManager::new();
|
||
|
||
manager.emit_event(Acc1410Event::PartitionCreated {
|
||
partition_id: [1u8; 32],
|
||
name: "Test Partition".to_string(),
|
||
partition_type: 1,
|
||
});
|
||
|
||
assert_eq!(manager.event_log.len(), 1);
|
||
assert_eq!(manager.event_counter, 1);
|
||
}
|
||
|
||
#[test]
|
||
fn test_event_listener() {
|
||
let mut manager = EventManager::new();
|
||
let listener = Arc::new(ConsoleEventListener::new("test".to_string()));
|
||
manager.add_listener(listener);
|
||
|
||
manager.emit_event(Acc1410Event::Transfer {
|
||
from: "user1".to_string(),
|
||
to: "user2".to_string(),
|
||
amount: 100,
|
||
partition_id: [1u8; 32],
|
||
});
|
||
|
||
assert_eq!(manager.event_log.len(), 1);
|
||
}
|
||
|
||
#[test]
|
||
fn test_query_events() {
|
||
let mut manager = EventManager::new();
|
||
|
||
// 添加多个事件
|
||
manager.emit_event(Acc1410Event::Transfer {
|
||
from: "user1".to_string(),
|
||
to: "user2".to_string(),
|
||
amount: 100,
|
||
partition_id: [1u8; 32],
|
||
});
|
||
|
||
manager.emit_event(Acc1410Event::Mint {
|
||
to: "user3".to_string(),
|
||
amount: 200,
|
||
partition_id: [2u8; 32],
|
||
});
|
||
|
||
// 查询所有事件
|
||
let filter = EventFilter {
|
||
event_types: None,
|
||
accounts: None,
|
||
partitions: None,
|
||
time_range: None,
|
||
};
|
||
|
||
let events = manager.query_events(&filter);
|
||
assert_eq!(events.len(), 2);
|
||
}
|
||
|
||
#[test]
|
||
fn test_get_account_events() {
|
||
let mut manager = EventManager::new();
|
||
|
||
manager.emit_event(Acc1410Event::Transfer {
|
||
from: "user1".to_string(),
|
||
to: "user2".to_string(),
|
||
amount: 100,
|
||
partition_id: [1u8; 32],
|
||
});
|
||
|
||
manager.emit_event(Acc1410Event::Mint {
|
||
to: "user1".to_string(),
|
||
amount: 200,
|
||
partition_id: [2u8; 32],
|
||
});
|
||
|
||
manager.emit_event(Acc1410Event::Transfer {
|
||
from: "user3".to_string(),
|
||
to: "user4".to_string(),
|
||
amount: 300,
|
||
partition_id: [1u8; 32],
|
||
});
|
||
|
||
let events = manager.get_account_events("user1");
|
||
assert_eq!(events.len(), 2);
|
||
}
|
||
|
||
#[test]
|
||
fn test_get_partition_events() {
|
||
let mut manager = EventManager::new();
|
||
|
||
let partition1 = [1u8; 32];
|
||
let partition2 = [2u8; 32];
|
||
|
||
manager.emit_event(Acc1410Event::Transfer {
|
||
from: "user1".to_string(),
|
||
to: "user2".to_string(),
|
||
amount: 100,
|
||
partition_id: partition1,
|
||
});
|
||
|
||
manager.emit_event(Acc1410Event::Mint {
|
||
to: "user3".to_string(),
|
||
amount: 200,
|
||
partition_id: partition2,
|
||
});
|
||
|
||
manager.emit_event(Acc1410Event::Transfer {
|
||
from: "user4".to_string(),
|
||
to: "user5".to_string(),
|
||
amount: 300,
|
||
partition_id: partition1,
|
||
});
|
||
|
||
let events = manager.get_partition_events(&partition1);
|
||
assert_eq!(events.len(), 2);
|
||
}
|
||
|
||
#[test]
|
||
fn test_get_recent_events() {
|
||
let mut manager = EventManager::new();
|
||
|
||
// 添加10个事件
|
||
for i in 0..10 {
|
||
manager.emit_event(Acc1410Event::Transfer {
|
||
from: format!("user{}", i),
|
||
to: format!("user{}", i + 1),
|
||
amount: 100,
|
||
partition_id: [1u8; 32],
|
||
});
|
||
}
|
||
|
||
let recent = manager.get_recent_events(5);
|
||
assert_eq!(recent.len(), 5);
|
||
assert_eq!(recent[0].event_id, 6);
|
||
assert_eq!(recent[4].event_id, 10);
|
||
}
|
||
|
||
#[test]
|
||
fn test_max_log_size() {
|
||
let mut manager = EventManager::new();
|
||
manager.set_max_log_size(5);
|
||
|
||
// 添加10个事件
|
||
for i in 0..10 {
|
||
manager.emit_event(Acc1410Event::Transfer {
|
||
from: format!("user{}", i),
|
||
to: format!("user{}", i + 1),
|
||
amount: 100,
|
||
partition_id: [1u8; 32],
|
||
});
|
||
}
|
||
|
||
// 日志应该只保留最后5个事件
|
||
assert_eq!(manager.event_log.len(), 5);
|
||
assert_eq!(manager.event_log[0].event_id, 6);
|
||
assert_eq!(manager.event_log[4].event_id, 10);
|
||
}
|
||
|
||
#[test]
|
||
fn test_event_statistics() {
|
||
let mut manager = EventManager::new();
|
||
|
||
manager.emit_event(Acc1410Event::Transfer {
|
||
from: "user1".to_string(),
|
||
to: "user2".to_string(),
|
||
amount: 100,
|
||
partition_id: [1u8; 32],
|
||
});
|
||
|
||
manager.emit_event(Acc1410Event::Mint {
|
||
to: "user3".to_string(),
|
||
amount: 200,
|
||
partition_id: [2u8; 32],
|
||
});
|
||
|
||
manager.emit_event(Acc1410Event::Burn {
|
||
from: "user4".to_string(),
|
||
amount: 50,
|
||
partition_id: [1u8; 32],
|
||
});
|
||
|
||
let stats = manager.get_event_statistics();
|
||
assert_eq!(stats.total_events, 3);
|
||
assert_eq!(stats.transfers, 1);
|
||
assert_eq!(stats.mints, 1);
|
||
assert_eq!(stats.burns, 1);
|
||
}
|
||
|
||
#[test]
|
||
fn test_remove_listener() {
|
||
let mut manager = EventManager::new();
|
||
let listener = Arc::new(ConsoleEventListener::new("test".to_string()));
|
||
manager.add_listener(listener);
|
||
|
||
assert_eq!(manager.listeners.len(), 1);
|
||
|
||
manager.remove_listener("test");
|
||
assert_eq!(manager.listeners.len(), 0);
|
||
}
|
||
}
|