diff --git a/rs/canister/api/can.did b/rs/canister/api/can.did index e04c5d8..a8ef57e 100644 --- a/rs/canister/api/can.did +++ b/rs/canister/api/can.did @@ -5,10 +5,8 @@ type AnonymizationInitConfig = record { }; type EventsArgs = record { start : nat64; length : nat64 }; type EventsResponse = record { - latest_event_index_v2 : opt nat64; events : vec IndexedEvent; latest_event_index : opt nat64; - is_v2 : bool; }; type IdempotentEvent = record { source : opt text; diff --git a/rs/canister/api/src/queries/events.rs b/rs/canister/api/src/queries/events.rs index a2a1302..58ceb0f 100644 --- a/rs/canister/api/src/queries/events.rs +++ b/rs/canister/api/src/queries/events.rs @@ -12,6 +12,4 @@ pub struct EventsArgs { pub struct EventsResponse { pub events: Vec, pub latest_event_index: Option, - pub latest_event_index_v2: Option, - pub is_v2: bool, } diff --git a/rs/canister/impl/src/memory.rs b/rs/canister/impl/src/memory.rs index f2bae4d..70e1b67 100644 --- a/rs/canister/impl/src/memory.rs +++ b/rs/canister/impl/src/memory.rs @@ -4,10 +4,8 @@ use ic_stable_structures::{ }; const UPGRADES: MemoryId = MemoryId::new(0); -const EVENTS_INDEX: MemoryId = MemoryId::new(1); -const EVENTS_DATA: MemoryId = MemoryId::new(2); -const EVENTS_V2_INDEX: MemoryId = MemoryId::new(3); -const EVENTS_V2_DATA: MemoryId = MemoryId::new(4); +const EVENTS_INDEX: MemoryId = MemoryId::new(3); +const EVENTS_DATA: MemoryId = MemoryId::new(4); const STRING_TO_NUM_MAP: MemoryId = MemoryId::new(5); const NUM_TO_STRING_INDEX: MemoryId = MemoryId::new(6); const NUM_TO_STRING_DATA: MemoryId = MemoryId::new(7); @@ -31,14 +29,6 @@ pub fn get_events_data_memory() -> Memory { get_memory(EVENTS_DATA) } -pub fn get_events_v2_index_memory() -> Memory { - get_memory(EVENTS_V2_INDEX) -} - -pub fn get_events_v2_data_memory() -> Memory { - get_memory(EVENTS_V2_DATA) -} - pub fn get_string_to_num_map_memory() -> Memory { get_memory(STRING_TO_NUM_MAP) } diff --git a/rs/canister/impl/src/model/events.rs b/rs/canister/impl/src/model/events.rs index 055f29d..7bcd6ee 100644 --- a/rs/canister/impl/src/model/events.rs +++ b/rs/canister/impl/src/model/events.rs @@ -1,4 +1,5 @@ use crate::memory::{get_events_data_memory, get_events_index_memory, Memory}; +use crate::model::string_to_num_map::StringToNumMap; use candid::Deserialize; use event_store_canister::{IdempotentEvent, IndexedEvent, TimestampMillis}; use ic_stable_structures::storable::Bound; @@ -10,6 +11,7 @@ use std::borrow::Cow; pub struct Events { #[serde(skip, default = "init_events")] events: StableLog, + string_to_num_map: StringToNumMap, } impl Events { @@ -18,14 +20,14 @@ impl Events { .iter() .skip(start as usize) .take(length as usize) - .map(|e| e.into()) + .map(|e| self.hydrate(e)) .collect() } pub fn push(&mut self, event: IdempotentEvent) { - self.events - .append(&StorableEvent::new(event.clone(), self.events.len())) - .unwrap(); + let storable = self.convert_to_storable(event, self.events.len()); + + self.events.append(&storable).unwrap(); } pub fn stats(&self) -> EventsStats { @@ -33,12 +35,48 @@ impl Events { latest_event_index: self.events.len().checked_sub(1), } } + + pub fn len(&self) -> u64 { + self.events.len() + } + + fn convert_to_storable(&mut self, event: IdempotentEvent, index: u64) -> StorableEvent { + StorableEvent { + index, + name: self.string_to_num_map.convert_to_num(event.name), + timestamp: event.timestamp, + user: event.user.map(|u| self.string_to_num_map.convert_to_num(u)), + source: event + .source + .map(|s| self.string_to_num_map.convert_to_num(s)), + payload: event.payload, + } + } + + fn hydrate(&self, event: StorableEvent) -> IndexedEvent { + IndexedEvent { + index: event.index, + name: self + .string_to_num_map + .convert_to_string(event.name) + .unwrap_or("unknown".to_string()), + timestamp: event.timestamp, + user: event + .user + .and_then(|u| self.string_to_num_map.convert_to_string(u)), + source: event + .source + .and_then(|s| self.string_to_num_map.convert_to_string(s)), + payload: event.payload, + } + } } impl Default for Events { fn default() -> Self { Events { events: init_events(), + string_to_num_map: StringToNumMap::default(), } } } @@ -56,13 +94,13 @@ struct StorableEvent { #[serde(rename = "i")] index: u64, #[serde(rename = "n")] - name: String, + name: u32, #[serde(rename = "t")] timestamp: TimestampMillis, #[serde(rename = "u", default, skip_serializing_if = "Option::is_none")] - user: Option, + user: Option, #[serde(rename = "s", default, skip_serializing_if = "Option::is_none")] - source: Option, + source: Option, #[serde( rename = "p", default, @@ -72,32 +110,6 @@ struct StorableEvent { payload: Vec, } -impl StorableEvent { - fn new(event: IdempotentEvent, index: u64) -> StorableEvent { - StorableEvent { - index, - name: event.name, - timestamp: event.timestamp, - user: event.user, - source: event.source, - payload: event.payload, - } - } -} - -impl From for IndexedEvent { - fn from(value: StorableEvent) -> Self { - IndexedEvent { - index: value.index, - name: value.name, - timestamp: value.timestamp, - user: value.user, - source: value.source, - payload: value.payload, - } - } -} - impl Storable for StorableEvent { fn to_bytes(&self) -> Cow<[u8]> { Cow::Owned(rmp_serde::to_vec_named(&self).unwrap()) diff --git a/rs/canister/impl/src/model/events_v2.rs b/rs/canister/impl/src/model/events_v2.rs deleted file mode 100644 index 496586e..0000000 --- a/rs/canister/impl/src/model/events_v2.rs +++ /dev/null @@ -1,128 +0,0 @@ -use crate::memory::{get_events_v2_data_memory, get_events_v2_index_memory, Memory}; -use crate::model::string_to_num_map::StringToNumMap; -use candid::Deserialize; -use event_store_canister::{IdempotentEvent, IndexedEvent, TimestampMillis}; -use ic_stable_structures::storable::Bound; -use ic_stable_structures::{StableLog, Storable}; -use serde::Serialize; -use std::borrow::Cow; - -#[derive(Serialize, Deserialize)] -pub struct EventsV2 { - #[serde(skip, default = "init_events")] - events: StableLog, - #[serde(default)] - string_to_num_map: StringToNumMap, -} - -impl EventsV2 { - pub fn get(&self, start: u64, length: u64) -> Vec { - self.events - .iter() - .skip(start as usize) - .take(length as usize) - .map(|e| self.hydrate(e)) - .collect() - } - - pub fn push(&mut self, event: IdempotentEvent) { - let storable = self.convert_to_storable(event, self.events.len()); - - self.events.append(&storable).unwrap(); - } - - pub fn stats(&self) -> EventsStats { - EventsStats { - latest_event_index: self.events.len().checked_sub(1), - } - } - - pub fn len(&self) -> u64 { - self.events.len() - } - - fn convert_to_storable(&mut self, event: IdempotentEvent, index: u64) -> StorableEvent { - StorableEvent { - index, - name: self.string_to_num_map.convert_to_num(event.name), - timestamp: event.timestamp, - user: event.user.map(|u| self.string_to_num_map.convert_to_num(u)), - source: event - .source - .map(|s| self.string_to_num_map.convert_to_num(s)), - payload: event.payload, - } - } - - fn hydrate(&self, event: StorableEvent) -> IndexedEvent { - IndexedEvent { - index: event.index, - name: self - .string_to_num_map - .convert_to_string(event.name) - .unwrap_or("unknown".to_string()), - timestamp: event.timestamp, - user: event - .user - .and_then(|u| self.string_to_num_map.convert_to_string(u)), - source: event - .source - .and_then(|s| self.string_to_num_map.convert_to_string(s)), - payload: event.payload, - } - } -} - -impl Default for EventsV2 { - fn default() -> Self { - EventsV2 { - events: init_events(), - string_to_num_map: StringToNumMap::default(), - } - } -} - -fn init_events() -> StableLog { - StableLog::init(get_events_v2_index_memory(), get_events_v2_data_memory()).unwrap() -} - -pub struct EventsStats { - pub latest_event_index: Option, -} - -#[derive(Serialize, Deserialize)] -struct StorableEvent { - #[serde(rename = "i")] - index: u64, - #[serde(rename = "n")] - name: u32, - #[serde(rename = "t")] - timestamp: TimestampMillis, - #[serde(rename = "u", default, skip_serializing_if = "Option::is_none")] - user: Option, - #[serde(rename = "s", default, skip_serializing_if = "Option::is_none")] - source: Option, - #[serde( - rename = "p", - default, - skip_serializing_if = "is_empty_slice", - with = "serde_bytes" - )] - payload: Vec, -} - -impl Storable for StorableEvent { - fn to_bytes(&self) -> Cow<[u8]> { - Cow::Owned(rmp_serde::to_vec_named(&self).unwrap()) - } - - fn from_bytes(bytes: Cow<[u8]>) -> Self { - rmp_serde::from_slice(bytes.as_ref()).unwrap() - } - - const BOUND: Bound = Bound::Unbounded; -} - -fn is_empty_slice(vec: &[T]) -> bool { - vec.is_empty() -} diff --git a/rs/canister/impl/src/model/mod.rs b/rs/canister/impl/src/model/mod.rs index 0cba7e3..d0cf31e 100644 --- a/rs/canister/impl/src/model/mod.rs +++ b/rs/canister/impl/src/model/mod.rs @@ -1,4 +1,3 @@ pub mod events; -pub mod events_v2; pub mod salt; mod string_to_num_map; diff --git a/rs/canister/impl/src/queries/events.rs b/rs/canister/impl/src/queries/events.rs index 4365e71..d37643e 100644 --- a/rs/canister/impl/src/queries/events.rs +++ b/rs/canister/impl/src/queries/events.rs @@ -7,18 +7,11 @@ use ic_cdk::query; fn events(args: EventsArgs) -> EventsResponse { state::read(|s| { let stats = s.events().stats(); - let stats_v2 = s.events_v2().stats(); - let (events, is_v2) = if stats.latest_event_index > stats_v2.latest_event_index { - (s.events().get(args.start, args.length), false) - } else { - (s.events_v2().get(args.start, args.length), true) - }; + let events = s.events().get(args.start, args.length); EventsResponse { events, latest_event_index: stats.latest_event_index, - latest_event_index_v2: stats_v2.latest_event_index, - is_v2, } }) } diff --git a/rs/canister/impl/src/state.rs b/rs/canister/impl/src/state.rs index 0e42f04..762cb06 100644 --- a/rs/canister/impl/src/state.rs +++ b/rs/canister/impl/src/state.rs @@ -1,6 +1,5 @@ use crate::env; use crate::model::events::Events; -use crate::model::events_v2::EventsV2; use crate::model::salt::Salt; use candid::Principal; use event_store_canister::{ @@ -21,9 +20,7 @@ thread_local! { pub struct State { push_events_whitelist: HashSet, read_events_whitelist: HashSet, - events: Events, - #[serde(default)] - events_v2: EventsV2, + events_v2: Events, event_deduper: EventDeduper, salt: Salt, anonymization_config: AnonymizationConfig, @@ -63,8 +60,7 @@ impl State { State { push_events_whitelist, read_events_whitelist, - events: Events::default(), - events_v2: EventsV2::default(), + events_v2: Events::default(), event_deduper: EventDeduper::default(), anonymization_config: anonymization_config.into(), salt: Salt::default(), @@ -89,10 +85,6 @@ impl State { } pub fn events(&self) -> &Events { - &self.events - } - - pub fn events_v2(&self) -> &EventsV2 { &self.events_v2 } @@ -125,15 +117,11 @@ impl State { } } - if self.events_v2.stats().latest_event_index >= self.events.stats().latest_event_index { - self.events_v2.push(event); - } else { - self.events.push(event); - } + self.events_v2.push(event); } pub fn migrate_events(&mut self, count: u32) { - for event in self.events.get(self.events_v2.len(), count as u64) { + for event in self.events_v2.get(self.events_v2.len(), count as u64) { self.events_v2.push(IdempotentEvent { idempotency_key: 0, name: event.name, diff --git a/rs/integration_tests/src/lib.rs b/rs/integration_tests/src/lib.rs index d3321a3..c928548 100644 --- a/rs/integration_tests/src/lib.rs +++ b/rs/integration_tests/src/lib.rs @@ -64,8 +64,7 @@ fn push_then_read_events_succeeds() { assert_eq!(read_response.events.len(), 5); assert_eq!(read_response.events.first().unwrap().index, 0); assert_eq!(read_response.events.last().unwrap().index, 4); - assert_eq!(read_response.latest_event_index, None); - assert_eq!(read_response.latest_event_index_v2, Some(9)); + assert_eq!(read_response.latest_event_index, Some(9)); } #[test_case(true, true)]