use crate::rpc::eth::filter::ActorEventBlock;
use crate::rpc::eth::filter::ParsedFilter;
use crate::rpc::eth::{filter::Filter, FilterID};
use crate::rpc::Arc;
use crate::shim::address::Address;
use crate::shim::clock::ChainEpoch;
use ahash::AHashMap as HashMap;
use anyhow::{Context, Result};
use cid::Cid;
use parking_lot::RwLock;
use std::any::Any;
#[allow(dead_code)]
#[derive(Debug, PartialEq)]
pub struct EventFilter {
id: FilterID,
min_height: ChainEpoch, max_height: ChainEpoch, tipset_cid: Cid,
addresses: Vec<Address>, keys_with_codec: HashMap<String, Vec<ActorEventBlock>>, max_results: usize, }
impl Filter for EventFilter {
fn id(&self) -> &FilterID {
&self.id
}
fn as_any(&self) -> &dyn Any {
self
}
}
pub struct EventFilterManager {
filters: RwLock<HashMap<FilterID, Arc<EventFilter>>>,
max_filter_results: usize,
}
impl EventFilterManager {
pub fn new(max_filter_results: usize) -> Arc<Self> {
Arc::new(Self {
filters: RwLock::new(HashMap::new()),
max_filter_results,
})
}
pub fn install(&self, pf: ParsedFilter) -> Result<Arc<EventFilter>> {
let id = FilterID::new().context("Failed to generate new FilterID")?;
let filter = Arc::new(EventFilter {
id: id.clone(),
min_height: pf.min_height,
max_height: pf.max_height,
tipset_cid: pf.tipset_cid,
addresses: pf.addresses,
keys_with_codec: pf.keys,
max_results: self.max_filter_results,
});
self.filters.write().insert(id, filter.clone());
Ok(filter)
}
pub fn remove(&self, id: &FilterID) -> Option<Arc<EventFilter>> {
let mut filters = self.filters.write();
filters.remove(id)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::rpc::eth::filter::ParsedFilter;
use crate::shim::address::Address;
use crate::shim::clock::ChainEpoch;
use cid::Cid;
#[test]
fn test_event_filter() {
let max_filter_results = 10;
let event_manager = EventFilterManager::new(max_filter_results);
let parsed_filter = ParsedFilter {
min_height: ChainEpoch::from(0),
max_height: ChainEpoch::from(100),
tipset_cid: Cid::default(),
addresses: vec![Address::new_id(123)],
keys: HashMap::new(),
};
let filter = event_manager
.install(parsed_filter)
.expect("Failed to install EventFilter");
let filter_id = filter.id().clone();
{
let filters = event_manager.filters.read();
assert!(filters.contains_key(&filter_id));
}
let removed = event_manager.remove(&filter_id);
assert_eq!(
removed,
Some(filter),
"Filter should be successfully removed"
);
{
let filters = event_manager.filters.read();
assert!(!filters.contains_key(&filter_id));
}
}
}